diff --git a/.eslintrc b/.eslintrc index acfa15464c596b9cdb22f86e4f3bd9adb5a710ce..8db623b85fc26abc113026782f77445e47a44b80 100644 --- a/.eslintrc +++ b/.eslintrc @@ -5,5 +5,31 @@ }, "extends": [ "pubsweet" - ] + ], + "parser": "babel-eslint", + "parserOptions": { + "allowImportExportEverywhere": true + }, + "rules": { + "camelcase": 0, + "consistent-return": 0, + "global-require": 0, + "jsx-a11y/anchor-is-valid": 0, + "jsx-a11y/click-events-have-key-events": 0, + "jsx-a11y/label-has-for": 0, + "jsx-a11y/no-static-element-interactions": 0, + "import/extensions": 0, + "import/no-dynamic-require": 0, + "import/no-extraneous-dependencies": 0, + "import/no-named-as-default": 0, + "import/no-named-as-default-member": 0, + "import/prefer-default-export": 0, + "no-console": ["error", { "allow": ["warn", "error"] }], + "no-param-reassign": 0, + "no-shadow": 0, + "no-underscore-dangle": 0, + "react/no-did-mount-set-state": 0, + "react/prop-types": 0, + "sort-keys": 0 + } } diff --git a/.prettierrc b/.prettierrc index 63b7777aac4961f6217197df86d7e2fcc4f98a5e..e3b414c7e09059b54efe16afa3519e065ca33675 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,6 +1,5 @@ { - "singleQuote": true, "semi": false, - "printWidth": 80, + "singleQuote": true, "trailingComma": "all" } diff --git a/.stylelintrc b/.stylelintrc index ef22505871e40998b18efe8eb185403b38b2c10d..4de0c088796debfc310a5d8117689a00469e42ec 100644 --- a/.stylelintrc +++ b/.stylelintrc @@ -1,8 +1,3 @@ { - "extends": "stylelint-config-standard", - "rules": { - "selector-pseudo-class-no-unknown": [true, { - "ignorePseudoClasses": ["global"] - }] - } + "extends": "stylelint-config-pubsweet" } diff --git a/package.json b/package.json index 81dc4a24f46a4fb392593303afdd7184ae4c46ac..085498ae12288afd01e9a02933c028267c2623a4 100644 --- a/package.json +++ b/package.json @@ -4,11 +4,12 @@ "private": true, "license": "MIT", "devDependencies": { - "babel-eslint": "^8.0.1", + "babel-eslint": "^8.0.2", "babel-preset-es2015": "^6.24.1", - "eslint": "^4.11.0", - "eslint-config-pubsweet": "^0.0.5", + "eslint": "^4.12.0", + "eslint-config-pubsweet": "^0.0.6", "eslint-plugin-import": "^2.8.0", + "eslint-plugin-jest": "^21.4.0", "eslint-plugin-jsx-a11y": "^6.0.2", "eslint-plugin-node": "^5.2.1", "eslint-plugin-prettier": "^2.3.1", @@ -20,7 +21,7 @@ "lint-staged": "^4.1.3", "prettier": "^1.8.2", "stylelint": "^8.2.0", - "stylelint-config-standard": "^17.0.0" + "stylelint-config-pubsweet": "^0.0.3" }, "repository": { "type": "git", @@ -28,16 +29,16 @@ }, "scripts": { "clean": "lerna clean", - "styleguide": "lerna run styleguide", - "test": "lerna run test", "lint": "npm run lint:js && npm run lint:style", "lint:js": "eslint packages", "lint:style": "stylelint packages/**/*.scss packages/**/*.css", - "precommit": "lint-staged" + "precommit": "lint-staged", + "styleguide": "lerna run styleguide", + "test": "lerna run test" }, "lint-staged": { "*.js": [ - "eslint", + "prettier --write", "git add" ], "*.css": "stylelint", diff --git a/packages/component-app/src/components/App.js b/packages/component-app/src/components/App.js index a65975f6d2d0332bed6370171577ef49bb6ea861..35f4a9d234fbfc6c75341ee2df9b5cb9f60a46dc 100644 --- a/packages/component-app/src/components/App.js +++ b/packages/component-app/src/components/App.js @@ -1,31 +1,31 @@ import React from 'react' import { compose } from 'recompose' import { connect } from 'react-redux' +// import PropTypes from 'prop-types' + import { AppBar } from 'xpub-ui' import { withJournal } from 'xpub-journal' import 'xpub-bootstrap' + import classes from './App.local.scss' const App = ({ children, currentUser, journal }) => ( <div className={classes.root}> <AppBar - brandName={journal.metadata.name} brandLink="/" - userName={currentUser ? currentUser.username : null} + brandName={journal.metadata.name} loginLink="/login" - logoutLink="/logout"/> + logoutLink="/logout" + userName={currentUser ? currentUser.username : null} + /> - <div className={classes.main}> - {children} - </div> + <div className={classes.main}>{children}</div> </div> ) export default compose( - connect( - state => ({ - currentUser: state.currentUser.user, - }) - ), - withJournal + connect(state => ({ + currentUser: state.currentUser.user, + })), + withJournal, )(App) diff --git a/packages/component-app/src/components/index.js b/packages/component-app/src/components/index.js index f52c042e6eb5482ae1d7e5189d7d08a9886e243e..f22feb838eb699bb29836d7c98d2c961079fa53c 100644 --- a/packages/component-app/src/components/index.js +++ b/packages/component-app/src/components/index.js @@ -1 +1,3 @@ -export { default as App } from './App' +import App from './App' + +export default App diff --git a/packages/component-app/src/index.js b/packages/component-app/src/index.js index 243220c28587a64c83710316cdaa8ec04ba8495d..6f1f42a64b1ecf4a71345e76fa416d89015cb96c 100644 --- a/packages/component-app/src/index.js +++ b/packages/component-app/src/index.js @@ -1,7 +1,5 @@ module.exports = { frontend: { - components: [ - () => require('./components') - ] + components: [() => require('./components')], }, } diff --git a/packages/component-authentication/src/components/Form.local.scss b/packages/component-authentication/src/components/Form.local.scss index 2c7c7a42ec1744dcd597d83c439c3722c65a7b94..8332e321e5586ddfd10128cb71f2ab0378c69df8 100644 --- a/packages/component-authentication/src/components/Form.local.scss +++ b/packages/component-authentication/src/components/Form.local.scss @@ -1,41 +1,41 @@ .root { font-family: "Fira Sans Condensed", sans-serif; - width: 30ch; margin: 0 auto; + width: 30ch; } .title { - text-align: left; - margin-bottom: 1.2em; font-size: 2em; + margin-bottom: 1.2em; + text-align: left; } .root input { - display: block; - width: 100%; border: 0 none; - padding: 0; border-bottom: 1px dashed #aaa; + display: block; font-family: "Fira Sans", sans-serif; + padding: 0; + width: 100%; - &:hover, - &:focus { - outline-style: none; - box-shadow: none; - border-color: transparent; - border-bottom: 1px dashed var(--color-primary); - } + // &:hover, + // &:focus { + // border-bottom: 1px dashed var(--color-primary); + // border-color: transparent; + // box-shadow: none; + // outline-style: none; + // } } .form { - margin-top: 1em; font-size: 0.8em; + margin-top: 1em; label { - display: block; cursor: text; - text-transform: lowercase; + display: block; font-style: italic; + text-transform: lowercase; &:hover { color: var(--color-primary); @@ -44,31 +44,39 @@ input { font-size: 1.3em; line-height: 1; - margin-top: 0.6em; margin-bottom: 3em; + margin-top: 0.6em; } } } +.root input:hover, +.root input:focus { + border-bottom: 1px dashed var(--color-primary); + border-color: transparent; + box-shadow: none; + outline-style: none; +} + .button { - margin-top: 1em; display: block; + margin-top: 1em; padding: 0.4em 2em; } .alternate { - margin-top: 1.6em; color: #777; - text-align: left; font-size: 0.8em; + margin-top: 1.6em; + text-align: left; .message { margin-right: 1ch; } .link { - color: var(--color-primary); border-bottom: 1px solid currentcolor; + color: var(--color-primary); cursor: pointer; } } diff --git a/packages/component-authentication/src/components/Login.js b/packages/component-authentication/src/components/Login.js index 0113eac6a850f87bec63e942d5fac29e54e72f6a..7441bbd33f141a8661da829422f6221046c3f0d2 100644 --- a/packages/component-authentication/src/components/Login.js +++ b/packages/component-authentication/src/components/Login.js @@ -4,32 +4,28 @@ import { Link } from 'react-router-dom' import { Button, TextField } from 'xpub-ui' import classes from './Form.local.scss' -const UsernameInput = props => ( - <TextField label="Username" {...props.input}/> -) +const UsernameInput = props => <TextField label="Username" {...props.input} /> const PasswordInput = props => ( - <TextField label="Password" {...props.input} type="password"/> + <TextField label="Password" {...props.input} type="password" /> ) const Login = ({ errorMessage, handleSubmit }) => ( <div className={classes.root}> - <div className={classes.title}> - Login - </div> + <div className={classes.title}>Login</div> {errorMessage && <div className={classes.error}>{errorMessage}</div>} - <form onSubmit={handleSubmit} className={classes.form}> - <Field name="username" component={UsernameInput}/> - <Field name="password" component={PasswordInput}/> - <Button primary type="submit" className={classes.button}>Login</Button> + <form className={classes.form} onSubmit={handleSubmit}> + <Field component={UsernameInput} name="username" /> + <Field component={PasswordInput} name="password" /> + <Button className={classes.button} primary type="submit"> + Login + </Button> </form> <div className={classes.alternate}> - <span className={classes.message}> - You don't have an account? - </span> - <Link to="/signup" className={classes.link}> + <span className={classes.message}>You don't have an account?</span> + <Link className={classes.link} to="/signup"> Sign up </Link> </div> diff --git a/packages/component-authentication/src/components/LoginPage.js b/packages/component-authentication/src/components/LoginPage.js index b9c100919100ed4399becc1877b584bd4c5b0b63..2f78b386d00ece5177096ad6a4f7a9833a637d24 100644 --- a/packages/component-authentication/src/components/LoginPage.js +++ b/packages/component-authentication/src/components/LoginPage.js @@ -15,26 +15,26 @@ const redirectPath = ({ location: { state } }) => { } const onSubmit = (values, dispatch, { history, location }) => { - dispatch(login(values)).then(() => { - history.push(redirectPath({ location })) - }).catch(error => { - if (error.validationErrors) { - throw new SubmissionError(error.validationErrors) - } else { - console.error(error) - // TODO: display error - } - }) + dispatch(login(values)) + .then(() => { + history.push(redirectPath({ location })) + }) + .catch(error => { + if (error.validationErrors) { + throw new SubmissionError(error.validationErrors) + } else { + console.error(error) + // TODO: display error + } + }) } export default compose( reduxForm({ form: 'login', - onSubmit + onSubmit, }), - connect( - state => ({ - error: state.login.error - }) - ) + connect(state => ({ + error: state.login.error, + })), )(Login) diff --git a/packages/component-authentication/src/components/LogoutPage.js b/packages/component-authentication/src/components/LogoutPage.js index a1f49406438f975b2c4b5a89da88a0c70d6c7cfc..cc3378af337233a55d76c48dcb9c973170d88765 100644 --- a/packages/component-authentication/src/components/LogoutPage.js +++ b/packages/component-authentication/src/components/LogoutPage.js @@ -5,15 +5,15 @@ import { Redirect } from 'react-router-dom' import { logout } from '../redux/logout' class Logout extends React.Component { - componentDidMount () { + componentDidMount() { const { isAuthenticated, logout } = this.props - if (isAuthenticated) { + if (isAuthenticated) { logout() } } - componentWillReceiveProps (nextProps) { + componentWillReceiveProps(nextProps) { const { isAuthenticated, logout } = nextProps if (isAuthenticated) { @@ -21,12 +21,10 @@ class Logout extends React.Component { } } - render () { + render() { const { isAuthenticated } = this.props - return isAuthenticated - ? <div>Signing out…</div> - : <Redirect to="/"/> + return isAuthenticated ? <div>Signing out…</div> : <Redirect to="/" /> } } @@ -36,7 +34,7 @@ export default compose( isAuthenticated: state.currentUser.isAuthenticated, }), { - logout - } - ) + logout, + }, + ), )(Logout) diff --git a/packages/component-authentication/src/components/PrivateRoute.js b/packages/component-authentication/src/components/PrivateRoute.js index 4a00b6073980492708c5569a04c7639a5ff8ef0d..7ef65bd770709795a55d0c704e691ef50280d266 100644 --- a/packages/component-authentication/src/components/PrivateRoute.js +++ b/packages/component-authentication/src/components/PrivateRoute.js @@ -4,27 +4,37 @@ import { connect } from 'react-redux' import { Route, Redirect, withRouter } from 'react-router-dom' import { getCurrentUser } from '../redux/currentUser' -const PrivateRoute = ({ currentUser, getCurrentUser, component: Component, ...rest }) => ( - <Route {...rest} render={props => { - if (!currentUser.isFetched) { - if (!currentUser.isFetching) { - getCurrentUser() - } +const PrivateRoute = ({ + currentUser, + getCurrentUser, + component: Component, + ...rest +}) => ( + <Route + {...rest} + render={props => { + if (!currentUser.isFetched) { + if (!currentUser.isFetching) { + getCurrentUser() + } - return <div>loading…</div> - } + return <div>loading…</div> + } - if (!currentUser.isAuthenticated) { - return ( - <Redirect to={{ - pathname: '/login', - state: { from: props.location } - }}/> - ) - } + if (!currentUser.isAuthenticated) { + return ( + <Redirect + to={{ + pathname: '/login', + state: { from: props.location }, + }} + /> + ) + } - return <Component {...props}/> - }}/> + return <Component {...props} /> + }} + /> ) export default compose( @@ -34,7 +44,7 @@ export default compose( currentUser: state.currentUser, }), { - getCurrentUser - } - ) + getCurrentUser, + }, + ), )(PrivateRoute) diff --git a/packages/component-authentication/src/components/Signup.js b/packages/component-authentication/src/components/Signup.js index 3c698b42ed708adfd6b48dd17c272455da3c97ac..8a95e222298f58b1a885c015faa5790d28dcb5ca 100644 --- a/packages/component-authentication/src/components/Signup.js +++ b/packages/component-authentication/src/components/Signup.js @@ -4,36 +4,32 @@ import { Link } from 'react-router-dom' import { Button, TextField } from 'xpub-ui' import classes from './Form.local.scss' -const UsernameInput = props => ( - <TextField label="Username" {...props.input}/> -) +const UsernameInput = props => <TextField label="Username" {...props.input} /> const EmailInput = props => ( - <TextField label="Email" {...props.input} type="email"/> + <TextField label="Email" {...props.input} type="email" /> ) const PasswordInput = props => ( - <TextField label="Password" {...props.input} type="password"/> + <TextField label="Password" {...props.input} type="password" /> ) const Signup = ({ errorMessage, handleSubmit }) => ( <div className={classes.root}> - <div className={classes.title}> - Sign up - </div> + <div className={classes.title}>Sign up</div> {errorMessage && <div className={classes.error}>{errorMessage}</div>} - <form onSubmit={handleSubmit} className={classes.form}> - <Field name="username" component={UsernameInput}/> - <Field name="email" component={EmailInput}/> - <Field name="password" component={PasswordInput}/> - <Button primary type="submit" className={classes.button}>Sign up</Button> + <form className={classes.form} onSubmit={handleSubmit}> + <Field component={UsernameInput} name="username" /> + <Field component={EmailInput} name="email" /> + <Field component={PasswordInput} name="password" /> + <Button className={classes.button} primary type="submit"> + Sign up + </Button> </form> <div className={classes.alternate}> - <span className={classes.message}> - Already have an account? - </span> - <Link to="/login" className={classes.link}> + <span className={classes.message}>Already have an account?</span> + <Link className={classes.link} to="/login"> Login </Link> </div> diff --git a/packages/component-authentication/src/components/SignupPage.js b/packages/component-authentication/src/components/SignupPage.js index a3d7e4d3808125b0879a8d74132b7ae4601fe5b9..0e8a0fffd625ffdb1b019ccfaeedfacad2eb92fd 100644 --- a/packages/component-authentication/src/components/SignupPage.js +++ b/packages/component-authentication/src/components/SignupPage.js @@ -18,11 +18,9 @@ const onSubmit = (values, dispatch) => { export default compose( reduxForm({ form: 'signup', - onSubmit + onSubmit, }), - connect( - state => ({ - error: state.signup.error - }) - ) + connect(state => ({ + error: state.signup.error, + })), )(Signup) diff --git a/packages/component-authentication/src/index.js b/packages/component-authentication/src/index.js index c5d562f66d9fedfb8f48b018bbe77c6fa73de2e2..44c18796cbf37e9b2319ab74efbbcdcff5a1a5a8 100644 --- a/packages/component-authentication/src/index.js +++ b/packages/component-authentication/src/index.js @@ -1,12 +1,10 @@ module.exports = { frontend: { - components: [ - () => require('./components') - ], + components: [() => require('./components')], reducers: { + currentUser: () => require('./redux/currentUser').default, login: () => require('./redux/login').default, signup: () => require('./redux/signup').default, - currentUser: () => require('./redux/currentUser').default - } + }, }, } diff --git a/packages/component-authentication/src/redux/currentUser.js b/packages/component-authentication/src/redux/currentUser.js index 67179d725b0fe48ee99e11c36250a87ab85b9a72..93b4c12a858104bcd8a7db7fce1774f277902cab 100644 --- a/packages/component-authentication/src/redux/currentUser.js +++ b/packages/component-authentication/src/redux/currentUser.js @@ -11,79 +11,77 @@ export const GET_CURRENT_USER_FAILURE = 'GET_CURRENT_USER_FAILURE' /* actions */ export const getCurrentUserRequest = () => ({ - type: GET_CURRENT_USER_REQUEST + type: GET_CURRENT_USER_REQUEST, }) export const getCurrentUserSuccess = user => ({ type: GET_CURRENT_USER_SUCCESS, - user + user, }) export const getCurrentUserFailure = error => ({ + error, type: GET_CURRENT_USER_FAILURE, - error }) export const getCurrentUser = () => dispatch => { dispatch(getCurrentUserRequest()) return api.get('/users/authenticate').then( - user => { - return dispatch(getCurrentUserSuccess(user)) - }, + user => dispatch(getCurrentUserSuccess(user)), error => { dispatch(getCurrentUserFailure(error)) throw error - } + }, ) } /* reducer */ const initialState = { - isFetching: false, - isFetched: false, + error: null, isAuthenticated: false, + isFetched: false, + isFetching: false, user: null, - error: null } export default (state = initialState, action) => { switch (action.type) { case GET_CURRENT_USER_REQUEST: return { - isFetching: true, - isFetched: false, + error: null, isAuthenticated: false, + isFetched: false, + isFetching: true, user: null, - error: null, } case GET_CURRENT_USER_FAILURE: return { - isFetching: false, - isFetched: true, + error: action.error, isAuthenticated: false, + isFetched: true, + isFetching: false, user: null, - error: action.error } case GET_CURRENT_USER_SUCCESS: return { - isFetching: false, - isFetched: true, + error: null, isAuthenticated: true, + isFetched: true, + isFetching: false, user: action.user, - error: null } // clear the current user on logout case LOGOUT_SUCCESS: return { - isFetching: false, - isFetched: false, + error: null, isAuthenticated: false, + isFetched: false, + isFetching: false, user: null, - error: null, } default: diff --git a/packages/component-authentication/src/redux/login.js b/packages/component-authentication/src/redux/login.js index a448f0c1d733e13c2a0a4ba6479918a1018c1216..706cb02549612e2b681d90706e927acc1416a3b5 100644 --- a/packages/component-authentication/src/redux/login.js +++ b/packages/component-authentication/src/redux/login.js @@ -21,11 +21,11 @@ export const loginSuccess = user => ({ }) export const loginFailure = error => ({ + error, type: LOGIN_FAILURE, - error }) -export const login = (credentials) => dispatch => { +export const login = credentials => dispatch => { dispatch(loginRequest()) return api.create('/users/authenticate', credentials).then( user => { @@ -36,35 +36,35 @@ export const login = (credentials) => dispatch => { error => { dispatch(loginFailure(error)) throw error - } + }, ) } /* reducer */ const initialState = { + error: null, isFetching: false, - error: null } export default (state = initialState, action) => { switch (action.type) { case LOGIN_REQUEST: return { + error: null, isFetching: true, - error: null } case LOGIN_SUCCESS: return { + error: null, isFetching: false, - error: null } case LOGIN_FAILURE: return { + error: action.error, isFetching: false, - error: action.error } default: diff --git a/packages/component-authentication/src/redux/logout.js b/packages/component-authentication/src/redux/logout.js index 570dc989c4b524c638eae7ea9f71015ef5168be6..63871ebb2a48ad1080d2dfee9f3b15772dc6e60e 100644 --- a/packages/component-authentication/src/redux/logout.js +++ b/packages/component-authentication/src/redux/logout.js @@ -5,7 +5,7 @@ export const LOGOUT_SUCCESS = 'LOGOUT_SUCCESS' /* actions */ export const logoutSuccess = () => ({ - type: LOGOUT_SUCCESS + type: LOGOUT_SUCCESS, }) export const logout = () => dispatch => { diff --git a/packages/component-authentication/src/redux/signup.js b/packages/component-authentication/src/redux/signup.js index 823a2698766a19de182ff2aba5ba27d53faefc8d..daa23590f8d875ad7355547dc629f4ba1be515b9 100644 --- a/packages/component-authentication/src/redux/signup.js +++ b/packages/component-authentication/src/redux/signup.js @@ -15,12 +15,12 @@ export const signupRequest = () => ({ export const signupSuccess = user => ({ type: SIGNUP_SUCCESS, - user + user, }) export const signupFailure = error => ({ + error, type: SIGNUP_FAILURE, - error }) export const signup = credentials => dispatch => { @@ -33,35 +33,35 @@ export const signup = credentials => dispatch => { error => { dispatch(signupFailure(error)) throw error - } + }, ) } /* reducer */ const initialState = { - isFetching: false, error: null, + isFetching: false, } export default (state = initialState, action) => { switch (action.type) { case SIGNUP_REQUEST: return { + error: null, isFetching: true, - error: null } case SIGNUP_SUCCESS: return { + error: null, isFetching: false, - error: null } case SIGNUP_FAILURE: return { + error: action.error, isFetching: false, - error: action.error } default: diff --git a/packages/component-authentication/styleguide.config.js b/packages/component-authentication/styleguide.config.js index 79f3ea499e304aad2a18546fe787b1493d856d4a..2c8697088f1d9f28b22dcae5474b05479c6aa9dd 100644 --- a/packages/component-authentication/styleguide.config.js +++ b/packages/component-authentication/styleguide.config.js @@ -1,17 +1,19 @@ module.exports = { title: 'xpub authentication style guide', styleguideComponents: { - StyleGuideRenderer: require.resolve('xpub-styleguide/src/components/StyleGuideRenderer'), - Wrapper: require.resolve('xpub-styleguide/src/components/Wrapper') + StyleGuideRenderer: require.resolve( + 'xpub-styleguide/src/components/StyleGuideRenderer', + ), + Wrapper: require.resolve('xpub-styleguide/src/components/Wrapper'), }, skipComponentsWithoutExample: true, serverPort: 6061, theme: { fontFamily: { - base: '"Fira Sans", sans-serif' + base: '"Fira Sans", sans-serif', }, color: { - link: 'cornflowerblue' - } - } + link: 'cornflowerblue', + }, + }, } diff --git a/packages/component-dashboard/src/components/AssignEditor.js b/packages/component-dashboard/src/components/AssignEditor.js index 007c6e65d74b0b64a8ac533a4892528f47fc40e5..a08077a9705faec48b409c7030237e485f7644c0 100644 --- a/packages/component-dashboard/src/components/AssignEditor.js +++ b/packages/component-dashboard/src/components/AssignEditor.js @@ -4,28 +4,36 @@ import { Menu } from 'xpub-ui' import { withJournal } from 'xpub-journal' // TODO: select multiple editors - -const AssignEditor = ({ journal, project, team, teamName, teamTypeName, options, addUserToTeam }) => ( +const AssignEditor = ({ + journal, + project, + team, + teamName, + teamTypeName, + options, + addUserToTeam, +}) => ( <Menu - value={team ? team.members[0] : null} label={teamName} - options={options} - placeholder="Assign an editor…" onChange={user => { addUserToTeam({ - team, - teamTypeName, - name: teamName, group: 'editor', + name: teamName, project, - user + team, + teamTypeName, + user, }) - }}/> + }} + options={options} + placeholder="Assign an editor…" + value={team ? team.members[0] : null} + /> ) export default compose( withJournal, withProps(({ journal, teamTypeName }) => ({ - teamName: journal.roles[teamTypeName] - })) + teamName: journal.roles[teamTypeName], + })), )(AssignEditor) diff --git a/packages/component-dashboard/src/components/AssignEditorContainer.js b/packages/component-dashboard/src/components/AssignEditorContainer.js index 2517a1c364548305a240148586feb8b152bf0e23..b39db3e709de8ee874e4a1fb72e1824625025d97 100644 --- a/packages/component-dashboard/src/components/AssignEditorContainer.js +++ b/packages/component-dashboard/src/components/AssignEditorContainer.js @@ -4,23 +4,30 @@ import AssignEditor from './AssignEditor' import { addUserToTeam } from '../redux/teams' const editorOption = user => ({ + label: user.username, // TODO: name value: user.id, - label: user.username // TODO: name }) export default compose( connect( (state, { project, teamTypeName }) => ({ - team: state.teams && state.teams - .find(team => team.object.type === 'collection' - && team.object.id === project.id - && team.teamType.name === teamTypeName), - options: state.users && !state.users.isFetching && state.users.users - // .filter(user => user.roles.includes(teamType)) // TODO - .map(editorOption) + options: + state.users && + !state.users.isFetching && + state.users.users + // .filter(user => user.roles.includes(teamType)) // TODO + .map(editorOption), + team: + state.teams && + state.teams.find( + team => + team.object.type === 'collection' && + team.object.id === project.id && + team.teamType.name === teamTypeName, + ), }), { - addUserToTeam - } - ) + addUserToTeam, + }, + ), )(AssignEditor) diff --git a/packages/component-dashboard/src/components/Dashboard.js b/packages/component-dashboard/src/components/Dashboard.js index e100fdbe63efc56cf131df60847f5769fe13f327..4cb225f0c1fabaccf9e0923957ef590f51730c7a 100644 --- a/packages/component-dashboard/src/components/Dashboard.js +++ b/packages/component-dashboard/src/components/Dashboard.js @@ -17,18 +17,23 @@ const Dashboard = ({ dashboard, deleteProject, reviewerResponse, - uploadManuscript + uploadManuscript, }) => ( <div className={classes.root}> <div className={classes.upload}> - <UploadManuscript conversion={conversion} uploadManuscript={uploadManuscript} /> + <UploadManuscript + conversion={conversion} + uploadManuscript={uploadManuscript} + /> </div> {!dashboard.owner.length && !dashboard.reviewer.length && !dashboard.editor.length && ( <div className={classes.section}> - <div className={classes.empty}>Nothing to do at the moment. Please upload a document.</div> + <div className={classes.empty}> + Nothing to do at the moment. Please upload a document. + </div> </div> )} @@ -36,7 +41,11 @@ const Dashboard = ({ <div className={classes.section}> <div className={classes.heading}>My Submissions</div> {dashboard.owner.map(project => ( - <OwnerItemWithVersion key={project.id} project={project} deleteProject={deleteProject} /> + <OwnerItemWithVersion + deleteProject={deleteProject} + key={project.id} + project={project} + /> ))} </div> )} @@ -46,9 +55,9 @@ const Dashboard = ({ <div className={classes.heading}>To review</div> {dashboard.reviewer.map(project => ( <ReviewerItemWithVersion + currentUser={currentUser} key={project.id} project={project} - currentUser={currentUser} reviewerResponse={reviewerResponse} /> ))} @@ -59,7 +68,11 @@ const Dashboard = ({ <div className={classes.section}> <div className={classes.heading}>My Manuscripts</div> {dashboard.editor.map(project => ( - <EditorItemWithVersion key={project.id} project={project} AssignEditor={AssignEditor} /> + <EditorItemWithVersion + AssignEditor={AssignEditor} + key={project.id} + project={project} + /> ))} </div> )} diff --git a/packages/component-dashboard/src/components/Dashboard.local.scss b/packages/component-dashboard/src/components/Dashboard.local.scss index 3ba7dea50f30045f9ae21e3ade523b8607e688f0..2612ee6232a5fcf5c0aac0f2b60d2c0de3c991d4 100644 --- a/packages/component-dashboard/src/components/Dashboard.local.scss +++ b/packages/component-dashboard/src/components/Dashboard.local.scss @@ -1,6 +1,6 @@ .root { - max-width: 60em; margin: auto; + max-width: 60em; } .upload { @@ -13,11 +13,11 @@ } .heading { - font-size: 1.6em; - text-transform: uppercase; - font-family: Vollkorn, serif; color: var(--color-primary); + font-family: Vollkorn, serif; + font-size: 1.6em; margin: 4em 0 2em; + text-transform: uppercase; } .empty { diff --git a/packages/component-dashboard/src/components/DashboardPage.js b/packages/component-dashboard/src/components/DashboardPage.js index b2dcfe4fee6984b5a6fe89572dd107d6f1899d4a..e8efaac3c80fbda1ddd7a9bd0a646e89b57f4505 100644 --- a/packages/component-dashboard/src/components/DashboardPage.js +++ b/packages/component-dashboard/src/components/DashboardPage.js @@ -11,11 +11,13 @@ import AssignEditorContainer from './AssignEditorContainer' const reviewerResponse = (project, version, reviewer, status) => dispatch => { reviewer.status = status - return dispatch(actions.updateFragment(project, { - id: version.id, - rev: version.rev, - reviewers: version.reviewers - })) + return dispatch( + actions.updateFragment(project, { + id: version.id, + rev: version.rev, + reviewers: version.reviewers, + }), + ) } export default compose( @@ -26,10 +28,9 @@ export default compose( ]), connect( state => { - const collections = state.collections - const teams = state.teams + const { collections } = state + const { conversion, teams } = state const currentUser = selectCurrentUser(state) - const conversion = state.conversion const sortedCollections = newestFirst(collections) @@ -40,33 +41,33 @@ export default compose( team => team.object.type === 'collection' && team.object.id === collection.id && - team.teamType.name === 'handlingEditor' - ) + team.teamType.name === 'handlingEditor', + ), ) const myCollections = teams .filter( team => team.group === 'editor' && team.object.type === 'collection' && - team.members.includes(currentUser.id) + team.members.includes(currentUser.id), ) .map(team => - collections.find(collection => collection.id === team.object.id) + collections.find(collection => collection.id === team.object.id), ) const dashboard = { - owner: sortedCollections.filter( - collection => - collection.owners && - collection.owners.some(owner => owner.id === currentUser.id) - ), editor: newestFirst( unassignedCollections .concat(myCollections) .filter( (collection, index, items) => - items.findIndex(item => item.id === collection.id) === index - ) + items.findIndex(item => item.id === collection.id) === index, + ), + ), + owner: sortedCollections.filter( + collection => + collection.owners && + collection.owners.some(owner => owner.id === currentUser.id), ), // reviewer: newestFirst(teams // .filter(team => team.group === 'reviewer' @@ -75,23 +76,28 @@ export default compose( // .map(team => collections.find(collection => { // return collection.id === team.object // }))), - reviewer: sortedCollections - .filter(collection => collection.reviewers - && collection.reviewers.some( - reviewer => reviewer && reviewer.user === currentUser.id - )), + reviewer: sortedCollections.filter( + collection => + collection.reviewers && + collection.reviewers.some( + reviewer => reviewer && reviewer.user === currentUser.id, + ), + ), } - return { collections, currentUser, conversion, dashboard } + return { collections, conversion, currentUser, dashboard } }, (dispatch, { history }) => ({ - uploadManuscript: acceptedFiles => dispatch(uploadManuscript(acceptedFiles, history)), - reviewerResponse: (project, version, reviewer, status) => dispatch(reviewerResponse(project, version, reviewer, status)), - deleteProject: collection => dispatch(actions.deleteCollection(collection)), - }) + deleteProject: collection => + dispatch(actions.deleteCollection(collection)), + reviewerResponse: (project, version, reviewer, status) => + dispatch(reviewerResponse(project, version, reviewer, status)), + uploadManuscript: acceptedFiles => + dispatch(uploadManuscript(acceptedFiles, history)), + }), ), withProps({ - AssignEditor: AssignEditorContainer + AssignEditor: AssignEditorContainer, }), withRouter, )(Dashboard) diff --git a/packages/component-dashboard/src/components/EmptySubmissions.js b/packages/component-dashboard/src/components/EmptySubmissions.js index 48e63c789761e88f4f3e3de94d177477a81d84bc..3b3f86b1335d38e06a205c6de9196b740af8e5c3 100644 --- a/packages/component-dashboard/src/components/EmptySubmissions.js +++ b/packages/component-dashboard/src/components/EmptySubmissions.js @@ -3,7 +3,7 @@ import classes from './EmptySubmissions.local.scss' const EmptySubmissions = () => ( <div className={classes.root}> - <div>You haven't submitted any manuscripts yet.</div> + <div>You haven't submitted any manuscripts yet.</div> </div> ) diff --git a/packages/component-dashboard/src/components/EmptySubmissions.local.scss b/packages/component-dashboard/src/components/EmptySubmissions.local.scss index b065fcb04fdc11cebb64da41eeaf2b49cc29b590..0d4fe50a4b81fb16a5960a7aed65712444e0de22 100644 --- a/packages/component-dashboard/src/components/EmptySubmissions.local.scss +++ b/packages/component-dashboard/src/components/EmptySubmissions.local.scss @@ -1,7 +1,7 @@ .root { + color: grey; font-family: var(--font-author); - font-style: italic; font-size: 1.2em; - color: grey; + font-style: italic; text-align: center; } diff --git a/packages/component-dashboard/src/components/ProjectLink.js b/packages/component-dashboard/src/components/ProjectLink.js index 42d6362a1d3cd3e23a73131771b6edeba212a406..0da34fafc6ece3d9b8784373214692521ea31708 100644 --- a/packages/component-dashboard/src/components/ProjectLink.js +++ b/packages/component-dashboard/src/components/ProjectLink.js @@ -24,9 +24,7 @@ const projectUrl = ({ project, version, page, id }) => { } const ProjectLink = props => ( - <Link to={projectUrl(props)}> - {props.children} - </Link> + <Link to={projectUrl(props)}>{props.children}</Link> ) export default ProjectLink diff --git a/packages/component-dashboard/src/components/Reviews.js b/packages/component-dashboard/src/components/Reviews.js index 81247a01341e524b0566949b8e867a7694b3718f..7eb86d258b43a7ca0b3e1620fa48af7022b2e2ed 100644 --- a/packages/component-dashboard/src/components/Reviews.js +++ b/packages/component-dashboard/src/components/Reviews.js @@ -7,8 +7,8 @@ import classes from './Reviews.local.scss' const Reviews = ({ reviews }) => ( <div className={classes.root}> {Object.keys(reviews).map(status => ( - <span key={status} className={classes.badge}> - <Badge count={reviews[status].length} label={status}/> + <span className={classes.badge} key={status}> + <Badge count={reviews[status].length} label={status} /> </span> ))} </div> @@ -16,6 +16,6 @@ const Reviews = ({ reviews }) => ( export default compose( withProps(props => ({ - reviews: groupBy(props.version.reviewers, 'status') - })) + reviews: groupBy(props.version.reviewers, 'status'), + })), )(Reviews) diff --git a/packages/component-dashboard/src/components/Status.js b/packages/component-dashboard/src/components/Status.js index 2fbe32352bbb3bd11646eb23a3d693225e28dc1f..cbac37d53e82b41b7dc501e173a0e31c9480d403 100644 --- a/packages/component-dashboard/src/components/Status.js +++ b/packages/component-dashboard/src/components/Status.js @@ -4,17 +4,15 @@ import classes from './Status.local.css' // TODO: move labels to journal config const labels = { - new: 'Unsubmitted', - submitted: 'Submitted', accepted: 'Accepted', assignedToEditor: 'Assigned to editor', - assigningReviewers: 'Assigning reviewers' + assigningReviewers: 'Assigning reviewers', + new: 'Unsubmitted', + submitted: 'Submitted', } const Status = ({ status }) => ( - <div className={classes.root}> - {labels[status] || 'Unsubmitted'} - </div> + <div className={classes.root}>{labels[status] || 'Unsubmitted'}</div> ) export default Status diff --git a/packages/component-dashboard/src/components/Status.local.css b/packages/component-dashboard/src/components/Status.local.css index 24ebf5e9254aa68d1eb55c42d7c72899feadfa22..125d12abeaf60f16cdc7309c2b0d08c4ed67a6bc 100644 --- a/packages/component-dashboard/src/components/Status.local.css +++ b/packages/component-dashboard/src/components/Status.local.css @@ -1,4 +1,4 @@ .root { - text-transform: uppercase; color: var(--color-primary); + text-transform: uppercase; } diff --git a/packages/component-dashboard/src/components/UploadManuscript.js b/packages/component-dashboard/src/components/UploadManuscript.js index 6dc78503a78c01e0be9c8f8f889107145cd667d4..eae6ef8c376792257d59b44bd95b0252fb8b8255 100644 --- a/packages/component-dashboard/src/components/UploadManuscript.js +++ b/packages/component-dashboard/src/components/UploadManuscript.js @@ -4,13 +4,14 @@ import classnames from 'classnames' import { Icon } from 'xpub-ui' import classes from './UploadManuscript.local.scss' -const isIdle = conversion => !(conversion.converting || conversion.complete || conversion.error) +const isIdle = conversion => + !(conversion.converting || conversion.complete || conversion.error) const UploadManuscript = ({ uploadManuscript, conversion }) => ( <Dropzone - onDrop={uploadManuscript} accept="application/vnd.openxmlformats-officedocument.wordprocessingml.document" className={classes.dropzone} + onDrop={uploadManuscript} > <div className={classes.root}> <div @@ -18,11 +19,13 @@ const UploadManuscript = ({ uploadManuscript, conversion }) => ( [classes.idle]: isIdle(conversion), [classes.converting]: conversion.converting, [classes.error]: conversion.error, - [classes.complete]: conversion.complete + [classes.complete]: conversion.complete, })} > <span className={classes.icon}> - <Icon color="var(--color-primary)">{conversion.complete ? 'check_circle' : 'plus_circle'}</Icon> + <Icon color="var(--color-primary)"> + {conversion.complete ? 'check_circle' : 'plus_circle'} + </Icon> </span> </div> diff --git a/packages/component-dashboard/src/components/UploadManuscript.local.scss b/packages/component-dashboard/src/components/UploadManuscript.local.scss index ed27b870b3db26f3ccf0175792b9760ea2fdf78f..00c659d396f68b9500600354cb63c72ff9132d3d 100644 --- a/packages/component-dashboard/src/components/UploadManuscript.local.scss +++ b/packages/component-dashboard/src/components/UploadManuscript.local.scss @@ -1,32 +1,21 @@ .dropzone { border: none; - display: inline-block; cursor: pointer; + display: inline-block; } .root { - font-weight: 200; display: flex; - padding-top: 10px; + font-weight: 200; padding-bottom: 10px; + padding-top: 10px; } .icon { - display: inline-flex; - height: 100%; align-items: center; color: var(--color-primary); -} - -.root:hover .idle { - circle { - fill: var(--color-primary); - stroke: var(--color-primary); - } - - line { - stroke: white; - } + display: inline-flex; + height: 100%; } .converting { @@ -39,9 +28,9 @@ } circle { - stroke-dashoffset: 0; - stroke-dasharray: 16; animation: spin 2s infinite linear; + stroke-dasharray: 16; + stroke-dashoffset: 0; stroke-linejoin: round; } } @@ -51,10 +40,10 @@ } .info { - text-transform: uppercase; + color: var(--color-primary); font-size: 2em; font-weight: 400; - color: var(--color-primary); + text-transform: uppercase; } .error { @@ -68,24 +57,35 @@ } .icon line { + stroke: var(--color-danger); transform: rotate(45deg) scale(2.8); transform-origin: 50% 50%; - stroke: var(--color-danger); + } +} + +.root:hover .idle { + circle { + fill: var(--color-primary); + stroke: var(--color-primary); + } + + line { + stroke: white; } } .complete { .icon { polyline { - stroke-dashoffset: 0; - stroke-dasharray: 100; animation: dash 1.35s linear; + stroke-dasharray: 100; + stroke-dashoffset: 0; } path { - stroke-dashoffset: 0; - stroke-dasharray: 100; animation: dash 0.75s linear; + stroke-dasharray: 100; + stroke-dashoffset: 0; } } } diff --git a/packages/component-dashboard/src/components/metadata/MetadataOwners.js b/packages/component-dashboard/src/components/metadata/MetadataOwners.js index b5615d81258ddd61fe2581bf98742ebf77d02380..40bb90e45ccbb5ca2b6e8abc2302c37361ae5aaa 100644 --- a/packages/component-dashboard/src/components/metadata/MetadataOwners.js +++ b/packages/component-dashboard/src/components/metadata/MetadataOwners.js @@ -3,10 +3,8 @@ import React from 'react' const MetadataOwners = ({ owners }) => ( <span> {owners.map((owner, index) => [ - index === 0 ? null : <span>{', '}</span>, - <span> - {owner.name || 'Anonymous'} - </span> + index === 0 ? null : <span>, </span>, + <span>{owner.name || 'Anonymous'}</span>, ])} </span> ) diff --git a/packages/component-dashboard/src/components/metadata/MetadataReviewType.js b/packages/component-dashboard/src/components/metadata/MetadataReviewType.js index 22db8985e90f83c3bfb91ab71b496409f399cc1e..11522e78d5df54c18c9174e2310687d258277feb 100644 --- a/packages/component-dashboard/src/components/metadata/MetadataReviewType.js +++ b/packages/component-dashboard/src/components/metadata/MetadataReviewType.js @@ -1,9 +1,7 @@ import React from 'react' const MetadataReviewType = ({ openReview }) => ( - <span> - {openReview ? 'Open review' : 'Closed review'} - </span> + <span>{openReview ? 'Open review' : 'Closed review'}</span> ) export default MetadataReviewType diff --git a/packages/component-dashboard/src/components/metadata/MetadataSections.js b/packages/component-dashboard/src/components/metadata/MetadataSections.js index a5a7b32450ea415f134b2f64a4eb4a2c2d816cf5..84594432b4a99a984e9e059be153a8d19d77dc17 100644 --- a/packages/component-dashboard/src/components/metadata/MetadataSections.js +++ b/packages/component-dashboard/src/components/metadata/MetadataSections.js @@ -4,10 +4,10 @@ import { withJournal } from 'xpub-journal' const MetadataSections = ({ journal, sections }) => ( <span> {sections.map((section, index) => [ - index === 0 ? null : <span>{', '}</span>, + index === 0 ? null : <span>, </span>, <span> {journal.articleSections.find(item => item.value === section).label} - </span> + </span>, ])} </span> ) diff --git a/packages/component-dashboard/src/components/metadata/MetadataSubmittedDate.js b/packages/component-dashboard/src/components/metadata/MetadataSubmittedDate.js index 46a0c441e4acbd315878d48ba544a502bcf913df..26e04a0f82fae6ea13fc72da9ed9bb34d4079d6a 100644 --- a/packages/component-dashboard/src/components/metadata/MetadataSubmittedDate.js +++ b/packages/component-dashboard/src/components/metadata/MetadataSubmittedDate.js @@ -2,9 +2,7 @@ import React from 'react' import Moment from 'react-moment' const MetadataSubmittedDate = ({ submitted }) => ( - <Moment format="YYYY-MM-DD"> - {submitted} - </Moment> + <Moment format="YYYY-MM-DD">{submitted}</Moment> ) export default MetadataSubmittedDate diff --git a/packages/component-dashboard/src/components/metadata/MetadataType.js b/packages/component-dashboard/src/components/metadata/MetadataType.js index e877cda694b7314db2a6a8e06d7a37a5fc9b4426..c17906048df62880f62140366b45d11959a4c0f8 100644 --- a/packages/component-dashboard/src/components/metadata/MetadataType.js +++ b/packages/component-dashboard/src/components/metadata/MetadataType.js @@ -2,9 +2,7 @@ import React from 'react' import { withJournal } from 'xpub-journal' const MetadataType = ({ journal, type }) => ( - <span> - {journal.articleTypes.find(item => item.value === type).label} - </span> + <span>{journal.articleTypes.find(item => item.value === type).label}</span> ) export default withJournal(MetadataType) diff --git a/packages/component-dashboard/src/components/sections/Divider.js b/packages/component-dashboard/src/components/sections/Divider.js index aef6dda9eaa910d825d117e4a09a9b5045b57c55..78f33a31662a5d0900da4d6b44e5453c4520eefb 100644 --- a/packages/component-dashboard/src/components/sections/Divider.js +++ b/packages/component-dashboard/src/components/sections/Divider.js @@ -2,7 +2,5 @@ import React from 'react' import classes from './Divider.local.scss' export default ({ separator }) => ( - <span className={classes.root}> - {' ' + separator + ' '} - </span> + <span className={classes.root}>{` ${separator} `}</span> ) diff --git a/packages/component-dashboard/src/components/sections/Divider.local.scss b/packages/component-dashboard/src/components/sections/Divider.local.scss index de6c4a17d55811030995b816edc8c7c21c743ec5..7a6bbe6d60e5af5ab094c37b20d593030ab8d157 100644 --- a/packages/component-dashboard/src/components/sections/Divider.local.scss +++ b/packages/component-dashboard/src/components/sections/Divider.local.scss @@ -1,5 +1,5 @@ .root { color: gray; - white-space: pre; font-style: normal; + white-space: pre; } diff --git a/packages/component-dashboard/src/components/sections/EditorItem.js b/packages/component-dashboard/src/components/sections/EditorItem.js index 84e91ed6e25e99e5b5933ec3247554a206c43044..902cec169cb1fffac36a2694f0311ff41b340d1e 100644 --- a/packages/component-dashboard/src/components/sections/EditorItem.js +++ b/packages/component-dashboard/src/components/sections/EditorItem.js @@ -14,74 +14,72 @@ import VersionTitle from './VersionTitle' const EditorItem = ({ AssignEditor, project, version, addUserToTeam }) => ( <div className={classes.root}> <div className={classes.header}> - <Status status={project.status}/> + <Status status={project.status} /> <div className={classes.meta}> - <MetadataOwners owners={project.owners}/> - <Divider separator="–"/> - <MetadataSubmittedDate submitted={version.submitted}/> - <Divider separator="–"/> - <MetadataType type={version.metadata.articleType}/> - <Divider separator="–"/> - <MetadataSections sections={version.metadata.articleSection}/> - <Divider separator="–"/> - <MetadataReviewType openReview={version.declarations.openReview}/> + <MetadataOwners owners={project.owners} /> + <Divider separator="–" /> + <MetadataSubmittedDate submitted={version.submitted} /> + <Divider separator="–" /> + <MetadataType type={version.metadata.articleType} /> + <Divider separator="–" /> + <MetadataSections sections={version.metadata.articleSection} /> + <Divider separator="–" /> + <MetadataReviewType openReview={version.declarations.openReview} /> </div> </div> <div className={classes.main}> - <VersionTitle version={version} className={classes.versionTitle}/> + <VersionTitle className={classes.versionTitle} version={version} /> <div className={classes.links}> <div className={classes.link}> {(!version.decision || version.decision.status !== 'submitted') && ( <span> - <ProjectLink - project={project} - version={version} - page="reviewers">Assign Reviewers</ProjectLink> + <ProjectLink page="reviewers" project={project} version={version}> + Assign Reviewers + </ProjectLink> - <Divider separator="|"/> + <Divider separator="|" /> </span> )} <ProjectLink + id={project.id} + page="decisions" project={project} version={version} - page="decisions" - id={project.id}> - {version.decision && version.decision.status === 'submitted' - ? `Decision: ${version.decision.recommendation}` - : 'Make decision'} + > + {version.decision && version.decision.status === 'submitted' + ? `Decision: ${version.decision.recommendation}` + : 'Make decision'} </ProjectLink> </div> </div> - <div className={classes.actions}/> + <div className={classes.actions} /> </div> - - <div className={classes.roles}> <div className={classes.role}> <AssignEditor + addUserToTeam={addUserToTeam} project={project} teamTypeName="seniorEditor" - addUserToTeam={addUserToTeam}/> + /> </div> <div className={classes.role}> <AssignEditor + addUserToTeam={addUserToTeam} project={project} teamTypeName="handlingEditor" - addUserToTeam={addUserToTeam}/> + /> </div> </div> <div className={classes.reviews}> - <Reviews - project={project} - version={version}/> + <Reviews project={project} version={version} /> </div> </div> ) diff --git a/packages/component-dashboard/src/components/sections/Item.local.scss b/packages/component-dashboard/src/components/sections/Item.local.scss index 4b69969edf599b6d0b590cbe7292b155793a076e..d80e49421cbfccfadbcadb3a706fb16bab70ede8 100644 --- a/packages/component-dashboard/src/components/sections/Item.local.scss +++ b/packages/component-dashboard/src/components/sections/Item.local.scss @@ -3,8 +3,8 @@ } .main { - display: flex; align-items: bottom; + display: flex; justify-content: flex-start; } @@ -16,10 +16,10 @@ .roles { display: flex; - text-transform: uppercase; font-size: 0.8em; margin-left: 0.5em; margin-top: 1em; + text-transform: uppercase; } .role:not(:last-of-type) { @@ -32,44 +32,44 @@ flex: 1; font-family: Vollkorn, serif; font-size: 1.6em; - margin-top: 0.2em; - padding-right: 0.4em; font-weight: 500; + margin-top: 0.2em; overflow: hidden; + padding-right: 0.4em; > span { background: white; - padding-right: 0.3em; display: inline; + padding-right: 0.3em; } &::after { - float: left; - width: 0; - font-weight: 400; color: lightgrey; - vertical-align: baseline; + content: ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . "". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . "". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . "". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . "". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . "". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . "; + float: left; font-size: 0.8em; + font-weight: 400; padding-top: 0.25em; + vertical-align: baseline; white-space: nowrap; - content: ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . "". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . "". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . "". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . "". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . "". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . "; + width: 0; } } .header { + align-items: baseline; display: flex; justify-content: space-between; margin-bottom: 0.4em; - align-items: baseline; } .meta { + color: #575757; display: flex; flex-wrap: nowrap; - white-space: nowrap; - color: #575757; font-size: 0.8em; margin-left: 1em; + white-space: nowrap; } .links { @@ -79,14 +79,14 @@ } .link { + color: var(--color-primary); + cursor: pointer; display: inline-block; - font-style: italic; font-size: 0.9em; + font-style: italic; padding: 0 0.3em; - color: var(--color-primary); - vertical-align: bottom; - cursor: pointer; padding-bottom: 0.3em; + vertical-align: bottom; &:last-child { margin-right: 0; @@ -103,16 +103,16 @@ .action button { background: none; - text-transform: none; border: none; cursor: pointer; + text-transform: none; } .reviews { - margin-top: 10px; - margin-bottom: 10px; display: inline-flex; justify-content: flex-end; + margin-bottom: 10px; + margin-top: 10px; } .editors { diff --git a/packages/component-dashboard/src/components/sections/OwnerItem.js b/packages/component-dashboard/src/components/sections/OwnerItem.js index a2d3c7a49fda4770cbb5de4455dc52ec07e8a92d..d122fccc2214e4ad47da4c717175febf47c86ee3 100644 --- a/packages/component-dashboard/src/components/sections/OwnerItem.js +++ b/packages/component-dashboard/src/components/sections/OwnerItem.js @@ -8,37 +8,33 @@ import VersionTitle from './VersionTitle' const OwnerItem = ({ project, version, deleteProject }) => ( <div className={classes.root}> <div className={classes.header}> - <Status status={project.status}/> + <Status status={project.status} /> </div> <div className={classes.main}> - <VersionTitle version={version} className={classes.versionTitle}/> + <VersionTitle className={classes.versionTitle} version={version} /> <div className={classes.links}> <div className={classes.link}> - <ProjectLink - project={project} - version={version} - page="submit">Submission</ProjectLink> + <ProjectLink page="submit" project={project} version={version}> + Submission + </ProjectLink> </div> - <Divider separator="|"/> + <Divider separator="|" /> <div className={classes.link}> - <ProjectLink - project={project} - version={version} - page="manuscript">Manuscript</ProjectLink> + <ProjectLink page="manuscript" project={project} version={version}> + Manuscript + </ProjectLink> </div> - <Divider separator="|"/> + <Divider separator="|" /> <div className={classes.link}> - <a onClick={() => deleteProject(project)} >Delete</a> + <a onClick={() => deleteProject(project)}>Delete</a> </div> - </div> - </div> </div> ) diff --git a/packages/component-dashboard/src/components/sections/ReviewerItem.js b/packages/component-dashboard/src/components/sections/ReviewerItem.js index 4fca6b3d11e24fcd7e74c58d4153d745757d435b..a4e5f7f082aa8acbe08b85fca0a4eef5fb89fff8 100644 --- a/packages/component-dashboard/src/components/sections/ReviewerItem.js +++ b/packages/component-dashboard/src/components/sections/ReviewerItem.js @@ -16,7 +16,7 @@ const ReviewerItem = ({ project, version, currentUser, reviewerResponse }) => { return ( <div className={classes.root}> <div className={classes.main}> - <VersionTitle version={version} className={classes.versionTitle}/> + <VersionTitle className={classes.versionTitle} version={version} /> {reviewer && ( <div> @@ -24,10 +24,11 @@ const ReviewerItem = ({ project, version, currentUser, reviewerResponse }) => { <div className={classes.links}> <div className={classes.link}> <ProjectLink + id={reviewer.id} + page="reviews" project={project} version={version} - page="reviews" - id={reviewer.id}> + > {reviewer.submitted ? 'Reviewed' : 'Do Review'} </ProjectLink> </div> @@ -37,20 +38,30 @@ const ReviewerItem = ({ project, version, currentUser, reviewerResponse }) => { {reviewer.status === 'invited' && ( <div className={classes.actions}> <div className={classes.action}> - <Button onClick={() => reviewerResponse(project, version, reviewer, 'accepted')}>accept</Button> + <Button + onClick={() => + reviewerResponse(project, version, reviewer, 'accepted') + } + > + accept + </Button> </div> - <Divider separator="|"/> + <Divider separator="|" /> <div className={classes.action}> - <Button onClick={() => reviewerResponse(project, version, reviewer, 'declined')}>reject</Button> + <Button + onClick={() => + reviewerResponse(project, version, reviewer, 'declined') + } + > + reject + </Button> </div> </div> )} - {reviewer.status === 'declined' && ( - <div>declined</div> - )} + {reviewer.status === 'declined' && <div>declined</div>} </div> )} </div> diff --git a/packages/component-dashboard/src/components/sections/VersionTitle.js b/packages/component-dashboard/src/components/sections/VersionTitle.js index a8240b6aeb2e5137845128fd8ccf3f22f19adb6a..d02f9ebd1c224e050f55ea8b370bb56b6910183d 100644 --- a/packages/component-dashboard/src/components/sections/VersionTitle.js +++ b/packages/component-dashboard/src/components/sections/VersionTitle.js @@ -1,18 +1,19 @@ import React from 'react' // import {TitleViewer} from 'xpub-edit/src/components' -export default ({version, className}) => { +export default ({ version, className }) => { // <TitleViewer // value={version && version.metadata && version.metadata.title || 'Untitled'} // className={className}/> - const title = version && version.metadata && version.metadata.title - ? version.metadata.title - : 'Untitled' + const title = + version && version.metadata && version.metadata.title + ? version.metadata.title + : 'Untitled' return ( <div className={className}> <span>{title}</span> </div> ) -} \ No newline at end of file +} diff --git a/packages/component-dashboard/src/components/withVersion.js b/packages/component-dashboard/src/components/withVersion.js index 4e3af13e43115cd33944739b27f3826efa408752..a3bddb4ba10d4ef2e4605ee949600bbf3875a050 100644 --- a/packages/component-dashboard/src/components/withVersion.js +++ b/packages/component-dashboard/src/components/withVersion.js @@ -4,15 +4,10 @@ import { actions } from 'pubsweet-client' import { ConnectPage } from 'xpub-connect' import { selectCurrentVersion } from 'xpub-selectors' -export default Component => ( +export default Component => compose( - ConnectPage(({project}) => [ - actions.getFragments({id: project.id}) - ]), - connect( - (state, {project}) => ({ - version: selectCurrentVersion(state, project) - }) - ) + ConnectPage(({ project }) => [actions.getFragments({ id: project.id })]), + connect((state, { project }) => ({ + version: selectCurrentVersion(state, project), + })), )(Component) -) diff --git a/packages/component-dashboard/src/index.js b/packages/component-dashboard/src/index.js index 684dc13816ad90b80833bd86fa7a3ae2f451f158..db614950b4cb56976125ba954e6c4d75b7560307 100644 --- a/packages/component-dashboard/src/index.js +++ b/packages/component-dashboard/src/index.js @@ -1,10 +1,8 @@ module.exports = { frontend: { - components: [ - () => require('./components') - ], + components: [() => require('./components')], reducers: { conversion: () => require('./redux/conversion').default, - } + }, }, } diff --git a/packages/component-dashboard/src/lib/title.js b/packages/component-dashboard/src/lib/title.js index de447467a76b552db09449b7fb179adaa45d517a..7aae47d80f251b4a25f856dc77739ca626d280a9 100644 --- a/packages/component-dashboard/src/lib/title.js +++ b/packages/component-dashboard/src/lib/title.js @@ -1,11 +1,10 @@ -export const generateTitle = (name) => { - return name +export const generateTitle = name => + name .replace(/[_-]+/g, ' ') // convert hyphens/underscores to space .replace(/\.[^.]+$/, '') // remove file extension -} // TODO: preserve italics (use parse5?) -export const extractTitle = (source) => { +export const extractTitle = source => { const doc = new DOMParser().parseFromString(source, 'text/html') const heading = doc.querySelector('h1') diff --git a/packages/component-dashboard/src/redux/conversion.js b/packages/component-dashboard/src/redux/conversion.js index 8cca2741c0e8868e8334dc88bad2579c7021a023..34892de2231136dd3b583c6355c182648cbe2159 100644 --- a/packages/component-dashboard/src/redux/conversion.js +++ b/packages/component-dashboard/src/redux/conversion.js @@ -12,18 +12,18 @@ export const UPLOAD_MANUSCRIPT_FAILURE = 'UPLOAD_MANUSCRIPT_FAILURE' /* actions */ export const uploadManuscriptRequest = () => ({ - type: UPLOAD_MANUSCRIPT_REQUEST + type: UPLOAD_MANUSCRIPT_REQUEST, }) export const uploadManuscriptSuccess = (collection, fragment) => ({ - type: UPLOAD_MANUSCRIPT_SUCCESS, collection, - fragment + fragment, + type: UPLOAD_MANUSCRIPT_SUCCESS, }) export const uploadManuscriptFailure = error => ({ + error, type: UPLOAD_MANUSCRIPT_FAILURE, - error }) export const uploadManuscript = (acceptedFiles, history) => dispatch => { @@ -53,40 +53,46 @@ export const uploadManuscript = (acceptedFiles, history) => dispatch => { const source = response.converted const title = extractTitle(source) || generateTitle(inputFile.name) - return dispatch(actions.createCollection({ title })).then(({collection}) => { - if (!collection.id) { - throw new Error('Failed to create a project') - } - - // TODO: create teams? - - // TODO: rethrow errors so they can be caught here - return dispatch(actions.createFragment(collection, { - fragmentType: 'version', - created: new Date(), // TODO: set on server - version: 1, - source, - metadata: { - title - }, - files: { - supplementary: [], - manuscript: { - name: inputFile.name, - url: fileURL - } + return dispatch(actions.createCollection({ title })).then( + ({ collection }) => { + if (!collection.id) { + throw new Error('Failed to create a project') } - })).then(({fragment}) => { - dispatch(uploadManuscriptSuccess(collection, fragment)) - - const route = `/projects/${collection.id}/versions/${fragment.id}/submit` - // redirect after a short delay - window.setTimeout(() => { - history.push(route) - }, 1000) - }) - }) + // TODO: create teams? + + // TODO: rethrow errors so they can be caught here + return dispatch( + actions.createFragment(collection, { + created: new Date(), // TODO: set on server + files: { + manuscript: { + name: inputFile.name, + url: fileURL, + }, + supplementary: [], + }, + fragmentType: 'version', + metadata: { + title, + }, + source, + version: 1, + }), + ).then(({ fragment }) => { + dispatch(uploadManuscriptSuccess(collection, fragment)) + + const route = `/projects/${collection.id}/versions/${ + fragment.id + }/submit` + + // redirect after a short delay + window.setTimeout(() => { + history.push(route) + }, 1000) + }) + }, + ) }) .catch(error => { console.error(error) @@ -99,31 +105,31 @@ export const uploadManuscript = (acceptedFiles, history) => dispatch => { /* reducer */ const initialState = { - converting: false, complete: undefined, - error: undefined + converting: false, + error: undefined, } export default (state = initialState, action) => { switch (action.type) { case UPLOAD_MANUSCRIPT_REQUEST: return { - converting: true, complete: false, - error: undefined + converting: true, + error: undefined, } case UPLOAD_MANUSCRIPT_SUCCESS: return { - converting: false, complete: true, + converting: false, } case UPLOAD_MANUSCRIPT_FAILURE: return { - converting: false, complete: false, - error: action.error + converting: false, + error: action.error, } default: diff --git a/packages/component-dashboard/src/redux/teams.js b/packages/component-dashboard/src/redux/teams.js index aad6e89e33008615ef81ccf3f17dd66f1ca1b182..ca90cef5a87b78e2ffdc86cee60f20f3a6160176 100644 --- a/packages/component-dashboard/src/redux/teams.js +++ b/packages/component-dashboard/src/redux/teams.js @@ -1,22 +1,31 @@ import { actions } from 'pubsweet-client' -export const addUserToTeam = ({ team, teamTypeName, name, group, project, user }) => dispatch => { +export const addUserToTeam = ({ + team, + teamTypeName, + name, + group, + project, + user, +}) => dispatch => { if (team) { team.members.push(user) return dispatch(actions.updateTeam(team)) } - return dispatch(actions.createTeam({ - teamType: { - name: teamTypeName, - permissions: 'editor' // TODO - }, - group, - name, - object: { - type: 'collection', - id: project.id - }, - members: [user] - })) + return dispatch( + actions.createTeam({ + teamType: { + name: teamTypeName, + permissions: 'editor', // TODO + }, + group, + name, + object: { + type: 'collection', + id: project.id, + }, + members: [user], + }), + ) } diff --git a/packages/component-dashboard/styleguide.config.js b/packages/component-dashboard/styleguide.config.js index 9b69f10428a6462f1944767f5a9c98923225bac5..d39338589931b7e4fe4c484c9d08b7e2e8e80803 100644 --- a/packages/component-dashboard/styleguide.config.js +++ b/packages/component-dashboard/styleguide.config.js @@ -1,20 +1,22 @@ module.exports = { title: 'xpub dashboard style guide', styleguideComponents: { - StyleGuideRenderer: require.resolve('xpub-styleguide/src/components/StyleGuideRenderer'), - Wrapper: require.resolve('xpub-styleguide/src/components/Wrapper') + StyleGuideRenderer: require.resolve( + 'xpub-styleguide/src/components/StyleGuideRenderer', + ), + Wrapper: require.resolve('xpub-styleguide/src/components/Wrapper'), }, context: { - faker: 'faker' + faker: 'faker', }, skipComponentsWithoutExample: true, serverPort: 6062, theme: { fontFamily: { - base: '"Fira Sans", sans-serif' + base: '"Fira Sans", sans-serif', }, color: { - link: 'cornflowerblue' - } - } + link: 'cornflowerblue', + }, + }, } diff --git a/packages/component-manuscript/src/components/Manuscript.js b/packages/component-manuscript/src/components/Manuscript.js index 113bc4b18c02a9ca9a8e28ef801116cf75aecc8e..722f4c2fa975f87781831e9d7c822de5a99f8091 100644 --- a/packages/component-manuscript/src/components/Manuscript.js +++ b/packages/component-manuscript/src/components/Manuscript.js @@ -5,17 +5,23 @@ import classes from './Manuscript.local.scss' // TODO: convert user teams to roles (see SimpleEditorWrapper)? -const Manuscript = ({ content, currentUser, fileUpload, history, updateManuscript }) => ( +const Manuscript = ({ + content, + currentUser, + fileUpload, + history, + updateManuscript, +}) => ( <SimpleEditor classes={classes.fullscreen} content={content} - user={currentUser} fileUpload={fileUpload} history={history} + onSave={source => updateManuscript({ source })} readOnly={false} trackChanges={false} update={data => updateManuscript(data)} - onSave={source => updateManuscript({ source })} + user={currentUser} /> ) diff --git a/packages/component-manuscript/src/components/Manuscript.local.scss b/packages/component-manuscript/src/components/Manuscript.local.scss index 6b2a948fa319de6694765871446e3ab084f06e32..de081595172684a37487d3de4f882b70ea848bd0 100644 --- a/packages/component-manuscript/src/components/Manuscript.local.scss +++ b/packages/component-manuscript/src/components/Manuscript.local.scss @@ -1,9 +1,9 @@ .fullscreen { - position: fixed; - top: 50px; - left: 0; - right: 0; - bottom: 0; background: white; + bottom: 0; + left: 0; overflow: hidden; + position: fixed; + right: 0; + top: 50px; } diff --git a/packages/component-manuscript/src/components/ManuscriptPage.js b/packages/component-manuscript/src/components/ManuscriptPage.js index ef878cd0666eefeed0837d553fa0b7ddfb148d21..47ee62a0d974b4bf770aa3e4f9ce630c7a4e0ba0 100644 --- a/packages/component-manuscript/src/components/ManuscriptPage.js +++ b/packages/component-manuscript/src/components/ManuscriptPage.js @@ -2,13 +2,20 @@ import { compose, withHandlers } from 'recompose' import { connect } from 'react-redux' import { actions } from 'pubsweet-client' import { ConnectPage } from 'xpub-connect' -import { selectCurrentUser, selectCollection, selectFragment } from 'xpub-selectors' +import { + selectCurrentUser, + selectCollection, + selectFragment, +} from 'xpub-selectors' import Manuscript from './Manuscript' export default compose( ConnectPage(({ match }) => [ actions.getCollection({ id: match.params.project }), - actions.getFragment({ id: match.params.project }, { id: match.params.version }) + actions.getFragment( + { id: match.params.project }, + { id: match.params.version }, + ), ]), connect( (state, { match }) => { @@ -18,20 +25,19 @@ export default compose( const content = version.source // TODO: load from a file - return { currentUser, project, version, content } + return { content, currentUser, project, version } }, { fileUpload: actions.fileUpload, - updateVersion: actions.updateFragment - } + updateVersion: actions.updateFragment, + }, ), withHandlers({ - updateManuscript: ({ updateVersion, project, version }) => data => { - return updateVersion(project, { + updateManuscript: ({ updateVersion, project, version }) => data => + updateVersion(project, { id: version.id, rev: version.rev, - ...data - }) - } - }) + ...data, + }), + }), )(Manuscript) diff --git a/packages/component-manuscript/src/index.js b/packages/component-manuscript/src/index.js index 0225ff41f4787662ca6fbc4ecc49c3894f11810c..6f1f42a64b1ecf4a71345e76fa416d89015cb96c 100644 --- a/packages/component-manuscript/src/index.js +++ b/packages/component-manuscript/src/index.js @@ -1,7 +1,5 @@ module.exports = { frontend: { - components: [ - () => require('./components') - ] - } + components: [() => require('./components')], + }, } diff --git a/packages/component-manuscript/styleguide.config.js b/packages/component-manuscript/styleguide.config.js index 9869e0b83404dc6cfd4ac7a2c15a4ebe13b2f147..79b898ac6b7c94d4a8d81aa9f2f8d212ac7edcc1 100644 --- a/packages/component-manuscript/styleguide.config.js +++ b/packages/component-manuscript/styleguide.config.js @@ -1,21 +1,23 @@ module.exports = { title: 'xpub-manuscript style guide', styleguideComponents: { - StyleGuideRenderer: require.resolve('xpub-styleguide/src/components/StyleGuideRenderer'), - Wrapper: require.resolve('xpub-styleguide/src/components/Wrapper') + StyleGuideRenderer: require.resolve( + 'xpub-styleguide/src/components/StyleGuideRenderer', + ), + Wrapper: require.resolve('xpub-styleguide/src/components/Wrapper'), }, context: { - faker: 'faker' + faker: 'faker', }, skipComponentsWithoutExample: true, webpackConfig: require('./webpack.config.js'), serverPort: 6063, theme: { fontFamily: { - base: '"Fira Sans", sans-serif' + base: '"Fira Sans", sans-serif', }, color: { - link: 'cornflowerblue' - } - } + link: 'cornflowerblue', + }, + }, } diff --git a/packages/component-review/src/components/DecisionPage.js b/packages/component-review/src/components/DecisionPage.js index 795400cbb648546bc1683f41196ff48c01fdcde5..3067b621f2cc90c7f60a5c24843b33191f159a5b 100644 --- a/packages/component-review/src/components/DecisionPage.js +++ b/packages/component-review/src/components/DecisionPage.js @@ -5,99 +5,116 @@ import { withRouter } from 'react-router-dom' import { reduxForm, SubmissionError } from 'redux-form' import { actions } from 'pubsweet-client' import { ConnectPage } from 'xpub-connect' -import { selectCollection, selectCurrentVersion, selectFragment, - selectFragments } from 'xpub-selectors' +import { + selectCollection, + selectCurrentVersion, + selectFragment, + selectFragments, +} from 'xpub-selectors' import uploadFile from 'xpub-upload' import DecisionLayout from './decision/DecisionLayout' // TODO: this should happen on the server -const handleDecision = (project, version) => dispatch => { - return dispatch(actions.updateFragment(project, { - id: version.id, - rev: version.rev, - decision: version.decision - })).then(() => { - console.log(version) +const handleDecision = (project, version) => dispatch => + dispatch( + actions.updateFragment(project, { + decision: version.decision, + id: version.id, + rev: version.rev, + }), + ).then(() => { + const cloned = pick(version, [ + 'source', + 'metadata', + 'declarations', + 'suggestions', + 'files', + 'notes', + ]) switch (version.decision.recommendation) { case 'accept': - return dispatch(actions.updateCollection({ - id: project.id, - rev: project.rev, - status: 'accepted' - })) + return dispatch( + actions.updateCollection({ + id: project.id, + rev: project.rev, + status: 'accepted', + }), + ) case 'reject': - return dispatch(actions.updateCollection({ - id: project.id, - rev: project.rev, - status: 'rejected' - })) + return dispatch( + actions.updateCollection({ + id: project.id, + rev: project.rev, + status: 'rejected', + }), + ) case 'revise': - const cloned = pick( - version, - ['source', 'metadata', 'declarations', 'suggestions', 'files', 'notes'] + return dispatch( + actions.updateCollection({ + id: project.id, + rev: project.rev, + status: 'revise', + }), + ).then(() => + dispatch( + actions.createFragment(project, { + fragmentType: 'version', + created: new Date(), // TODO: set on server + ...cloned, + version: version.version + 1, + }), + ), ) - return dispatch(actions.updateCollection({ - id: project.id, - rev: project.rev, - status: 'revise' - })).then(() => dispatch(actions.createFragment(project, { - fragmentType: 'version', - created: new Date(), // TODO: set on server - ...cloned, - version: version.version + 1, - }))) - default: throw new Error('Unknown decision type') } }) -} const onSubmit = (values, dispatch, { project, version, history }) => { - console.log('submit', values) - version.decision = { ...version.decision, ...values, + status: 'submitted', submitted: new Date(), - status: 'submitted' } - return dispatch(handleDecision(project, version)).then(() => { - // TODO: show "thanks for your review" message - history.push('/') - }).catch(error => { - if (error.validationErrors) { - throw new SubmissionError() - } - }) + return dispatch(handleDecision(project, version)) + .then(() => { + // TODO: show "thanks for your review" message + history.push('/') + }) + .catch(error => { + if (error.validationErrors) { + throw new SubmissionError() + } + }) } const onChange = (values, dispatch, { project, version }) => { - console.log('change', values) - version.decision = { ...version.decision, - ...values + ...values, } - return dispatch(actions.updateFragment(project, { - id: version.id, - rev: version.rev, - decision: version.decision - })) + return dispatch( + actions.updateFragment(project, { + decision: version.decision, + id: version.id, + rev: version.rev, + }), + ) // TODO: display a notification when saving/saving completes/saving fails } export default compose( ConnectPage(({ match }) => [ - actions.getCollection({id: match.params.project}), - actions.getFragments({id: match.params.project}), + actions.getCollection({ id: match.params.project }), + actions.getFragments({ id: match.params.project }), ]), connect( (state, { match }) => { @@ -106,21 +123,19 @@ export default compose( const version = selectFragment(state, match.params.version) const currentVersion = selectCurrentVersion(state, project) - return { project, versions, version, currentVersion } + return { currentVersion, project, version, versions } }, { - uploadFile - } + uploadFile, + }, ), withRouter, - withProps(({decision}) => { - return { - initialValues: decision - } - }), + withProps(({ decision }) => ({ + initialValues: decision, + })), reduxForm({ form: 'decision', + onChange: debounce(onChange, 1000, { maxWait: 5000 }), onSubmit, - onChange: debounce(onChange, 1000, { maxWait: 5000 }) - }) + }), )(DecisionLayout) diff --git a/packages/component-review/src/components/ReviewPage.js b/packages/component-review/src/components/ReviewPage.js index 485ee1d98bb6e84500cbb0d5f42ef6e4262a692c..1666c989b6a8c2cf0f549cca347ad01791362d2f 100644 --- a/packages/component-review/src/components/ReviewPage.js +++ b/packages/component-review/src/components/ReviewPage.js @@ -5,46 +5,60 @@ import { withRouter } from 'react-router-dom' import { reduxForm, SubmissionError } from 'redux-form' import { actions } from 'pubsweet-client' import { ConnectPage } from 'xpub-connect' -import { selectCurrentUser, selectCollection, selectFragments, selectCurrentVersion, selectFragment, selectUser, getReviewerFromUser } from 'xpub-selectors' +import { + selectCurrentUser, + selectCollection, + selectFragments, + selectCurrentVersion, + selectFragment, + selectUser, + getReviewerFromUser, +} from 'xpub-selectors' import uploadFile from 'xpub-upload' import ReviewLayout from './review/ReviewLayout' -const onSubmit = (values, dispatch, { history, project, version, reviewer }) => { - console.log('submit', values) - +const onSubmit = ( + values, + dispatch, + { history, project, version, reviewer }, +) => { Object.assign(reviewer, { - submitted: new Date(), status: 'reviewed', - ...values + submitted: new Date(), + ...values, }) - return dispatch(actions.updateFragment(project, { - id: version.id, - rev: version.rev, - reviewers: version.reviewers - })).then(() => { - // TODO: show "thanks for your review" message - history.push('/') - }).catch(error => { - if (error.validationErrors) { - throw new SubmissionError() - } - }) + return dispatch( + actions.updateFragment(project, { + id: version.id, + rev: version.rev, + reviewers: version.reviewers, + }), + ) + .then(() => { + // TODO: show "thanks for your review" message + history.push('/') + }) + .catch(error => { + if (error.validationErrors) { + throw new SubmissionError() + } + }) } const onChange = (values, dispatch, { project, version, reviewer }) => { - console.log('change', values) - Object.assign(reviewer, { submitted: new Date(), - ...values + ...values, }) - return dispatch(actions.updateFragment(project, { - id: version.id, - rev: version.rev, - reviewers: version.reviewers - })) + return dispatch( + actions.updateFragment(project, { + id: version.id, + rev: version.rev, + reviewers: version.reviewers, + }), + ) // TODO: display a notification when saving/saving completes/saving fails } @@ -64,29 +78,37 @@ export default compose( const version = selectFragment(state, match.params.version) const currentVersion = selectCurrentVersion(state, project) - const handlingEditors = state.teams.find(team => ( - team.object.type === 'collection' - && team.object.id === match.params.project - && team.teamType.name === 'handlingEditor' - )).members.map(id => selectUser(state, id)) + const handlingEditors = state.teams + .find( + team => + team.object.type === 'collection' && + team.object.id === match.params.project && + team.teamType.name === 'handlingEditor', + ) + .members.map(id => selectUser(state, id)) const reviewer = getReviewerFromUser(project, currentVersion, currentUser) - return { project, versions, version, currentVersion, reviewer, handlingEditors } + return { + currentVersion, + handlingEditors, + project, + reviewer, + version, + versions, + } }, { - uploadFile - } + uploadFile, + }, ), withRouter, - withProps(({ reviewer }) => { - return { - initialValues: reviewer, - } - }), + withProps(({ reviewer }) => ({ + initialValues: reviewer, + })), reduxForm({ form: 'review', + onChange: debounce(onChange, 1000, { maxWait: 5000 }), onSubmit, - onChange: debounce(onChange, 1000, { maxWait: 5000 }) - }) + }), )(ReviewLayout) diff --git a/packages/component-review/src/components/ReviewersPage.js b/packages/component-review/src/components/ReviewersPage.js index c1e814c3ddce666afe3338d52362bedacad431fc..3b8dfa8c4cd399e1910919d6fc047b2451ff08d2 100644 --- a/packages/component-review/src/components/ReviewersPage.js +++ b/packages/component-review/src/components/ReviewersPage.js @@ -16,34 +16,34 @@ export default compose( actions.getUsers(), // actions.getFragment({ id: match.params.project }, { id: match.params.version }), ]), - connect( - (state, { match }) => { - const project = selectCollection(state, match.params.project) - const version = selectFragment(state, match.params.version) - const reviewers = (version.reviewers || []).filter(reviewer => reviewer.reviewer) + connect((state, { match }) => { + const project = selectCollection(state, match.params.project) + const version = selectFragment(state, match.params.version) + const reviewers = (version.reviewers || []).filter( + reviewer => reviewer.reviewer, + ) - const reviewerUsers = state.users.users - // const reviewerUsers = filter(state.users.users, { reviewer: true }) + const reviewerUsers = state.users.users + // const reviewerUsers = filter(state.users.users, { reviewer: true }) - // populate the reviewer user - // TODO: remove these, as they'll get saved back to the server - reviewers.forEach(reviewer => { - const projectReviewer = find(project.reviewers, { - id: reviewer.reviewer - }) - - reviewer._user = find(reviewerUsers, { - id: projectReviewer.user - }) + // populate the reviewer user + // TODO: remove these, as they'll get saved back to the server + reviewers.forEach(reviewer => { + const projectReviewer = find(project.reviewers, { + id: reviewer.reviewer, + }) - reviewer._reviewer = projectReviewer + reviewer._user = find(reviewerUsers, { + id: projectReviewer.user, }) - return { project, version, reviewers, reviewerUsers } - } - ), + reviewer._reviewer = projectReviewer + }) + + return { project, reviewers, reviewerUsers, version } + }), withProps({ + Reviewer: ReviewerContainer, ReviewerForm: ReviewerFormContainer, - Reviewer: ReviewerContainer - }) + }), )(Reviewers) diff --git a/packages/component-review/src/components/decision/Decision.js b/packages/component-review/src/components/decision/Decision.js index 53fa8a27b632e84b45cac932f3fbc1c5e3092523..f23e1b1a5de6b6d3a8eb5920a57b740d141110f6 100644 --- a/packages/component-review/src/components/decision/Decision.js +++ b/packages/component-review/src/components/decision/Decision.js @@ -6,26 +6,22 @@ import classes from './Decision.local.scss' const Decision = ({ decision }) => ( <div> <div> - <div className={classes.heading}> - Note - </div> + <div className={classes.heading}>Note</div> <div className={classes.note}> <div className={classes.content}> - <NoteViewer value={decision.note.content}/> + <NoteViewer value={decision.note.content} /> </div> - {decision.note.attachments - && decision.note.attachments.map(attachment => ( - <Attachment key={attachment.url} value={attachment}/> - ))} + {decision.note.attachments && + decision.note.attachments.map(attachment => ( + <Attachment key={attachment.url} value={attachment} /> + ))} </div> </div> <div> - <div className={classes.heading}> - Decision - </div> + <div className={classes.heading}>Decision</div> <div className={classes.decision}>{decision.recommendation}</div> </div> diff --git a/packages/component-review/src/components/decision/Decision.local.scss b/packages/component-review/src/components/decision/Decision.local.scss index 7a704a3b3963cd633510dfbffe60687ab948833f..4ee5ac241b4d4d521b546ab1ce800ccf9aea35df 100644 --- a/packages/component-review/src/components/decision/Decision.local.scss +++ b/packages/component-review/src/components/decision/Decision.local.scss @@ -1,7 +1,7 @@ .heading { font-weight: bold; - margin-top: 20px; margin-bottom: 10px; + margin-top: 20px; } .note { diff --git a/packages/component-review/src/components/decision/DecisionForm.js b/packages/component-review/src/components/decision/DecisionForm.js index 5d1576499262c0a353bf272d2975c3060637ed34..ed32ac84f01625e70ba214cd120dab0d09d2abe5 100644 --- a/packages/component-review/src/components/decision/DecisionForm.js +++ b/packages/component-review/src/components/decision/DecisionForm.js @@ -1,29 +1,22 @@ import React from 'react' import { FormSection } from 'redux-form' -import { Button } from 'xpub-ui' import { NoteEditor } from 'xpub-edit' -import { Attachments, RadioGroup, ValidatedField } from 'xpub-ui' +import { Attachments, Button, RadioGroup, ValidatedField } from 'xpub-ui' import { withJournal } from 'xpub-journal' import { required } from 'xpub-validators' import classes from './DecisionForm.local.scss' -const NoteInput = input => - <NoteEditor - title="Decision" - placeholder="Enter your decision…" - {...input}/> +const NoteInput = input => ( + <NoteEditor placeholder="Enter your decision…" title="Decision" {...input} /> +) -const AttachmentsInput = uploadFile => input => - <Attachments - uploadFile={uploadFile} - {...input}/> +const AttachmentsInput = uploadFile => input => ( + <Attachments uploadFile={uploadFile} {...input} /> +) -const RecommendationInput = journal => input => - <RadioGroup - inline - required - options={journal.recommendations} - {...input}/> +const RecommendationInput = journal => input => ( + <RadioGroup inline options={journal.recommendations} required {...input} /> +) const DecisionForm = ({ journal, valid, handleSubmit, uploadFile }) => ( <form onSubmit={handleSubmit}> @@ -32,27 +25,32 @@ const DecisionForm = ({ journal, valid, handleSubmit, uploadFile }) => ( <div className={classes.note}> <div className={classes.content}> <ValidatedField + component={NoteInput} name="content" validate={[required]} - component={NoteInput}/> + /> </div> <ValidatedField + component={AttachmentsInput(uploadFile)} name="attachments" - component={AttachmentsInput(uploadFile)}/> + /> </div> </FormSection> </div> <div className={classes.section}> <ValidatedField + component={RecommendationInput(journal)} name="recommendation" validate={[required]} - component={RecommendationInput(journal)}/> + /> </div> <div> - <Button type="submit" primary disabled={!valid}>Submit</Button> + <Button disabled={!valid} primary type="submit"> + Submit + </Button> </div> </form> ) diff --git a/packages/component-review/src/components/decision/DecisionForm.local.scss b/packages/component-review/src/components/decision/DecisionForm.local.scss index e39f5b85fc7ce105479837ccb835610e985cdf74..035a1105eeba11b21a632212badf014cdb97c4d5 100644 --- a/packages/component-review/src/components/decision/DecisionForm.local.scss +++ b/packages/component-review/src/components/decision/DecisionForm.local.scss @@ -1,6 +1,6 @@ .section { - margin-top: 20px; margin-bottom: 20px; + margin-top: 20px; } .note { diff --git a/packages/component-review/src/components/decision/DecisionLayout.js b/packages/component-review/src/components/decision/DecisionLayout.js index 776abcd078561a612112347d4d04c78d78c7fdf6..295bed8ad929a8878fc3075c6c19a20cbd9660c3 100644 --- a/packages/component-review/src/components/decision/DecisionLayout.js +++ b/packages/component-review/src/components/decision/DecisionLayout.js @@ -9,13 +9,20 @@ import ReviewMetadata from '../metadata/ReviewMetadata' import Decision from './Decision' import Tabs from '../tabs/Tabs' -const DecisionLayout = ({ project, versions, currentVersion, valid, handleSubmit, uploadFile }) => { +const DecisionLayout = ({ + project, + versions, + currentVersion, + valid, + handleSubmit, + uploadFile, +}) => { const decisionSections = [] const editorSections = [] versions.forEach(version => { // TODO: allow multiple decisions, e.g. appeals - const decision = version.decision + const { decision } = version if (decision && decision.submitted) { const submittedMoment = moment(decision.submitted) @@ -23,29 +30,28 @@ const DecisionLayout = ({ project, versions, currentVersion, valid, handleSubmit const label = submittedMoment.format('YYYY-MM-DD') decisionSections.push({ - key, - label, content: ( <div> - <ReviewMetadata version={version}/> - <DecisionReviews version={version}/> - <Decision decision={decision}/> + <ReviewMetadata version={version} /> + <DecisionReviews version={version} /> + <Decision decision={decision} /> </div> ), + key, + label, }) editorSections.push({ + content: ( + <SimpleEditor content={version.source} layout="bare" readOnly /> + ), key, label, - content: <SimpleEditor - content={version.source} - layout="bare" - readOnly={true}/> }) } }, []) - const decision = currentVersion.decision + const { decision } = currentVersion if (!decision || !decision.submitted) { const submittedMoment = moment() @@ -53,30 +59,28 @@ const DecisionLayout = ({ project, versions, currentVersion, valid, handleSubmit const label = submittedMoment.format('YYYY-MM-DD') decisionSections.push({ - key, - label, content: ( <div> - <ReviewMetadata - version={currentVersion}/> - <DecisionReviews - version={currentVersion}/> + <ReviewMetadata version={currentVersion} /> + <DecisionReviews version={currentVersion} /> <DecisionForm decision={decision} - valid={valid} handleSubmit={handleSubmit} - uploadFile={uploadFile}/> + uploadFile={uploadFile} + valid={valid} + /> </div> - ) + ), + key, + label, }) editorSections.push({ + content: ( + <SimpleEditor content={currentVersion.source} layout="bare" readOnly /> + ), key, label, - content: <SimpleEditor - content={currentVersion.source} - layout="bare" - readOnly={true}/> }) } @@ -84,16 +88,18 @@ const DecisionLayout = ({ project, versions, currentVersion, valid, handleSubmit <div className={classes.root}> <div className={classes.column}> <Tabs - sections={editorSections} activeKey={editorSections[editorSections.length - 1].key} - title="Versions"/> + sections={editorSections} + title="Versions" + /> </div> <div className={classes.column}> <Tabs - sections={decisionSections} activeKey={decisionSections[decisionSections.length - 1].key} - title="Versions"/> + sections={decisionSections} + title="Versions" + /> </div> </div> ) diff --git a/packages/component-review/src/components/decision/DecisionLayout.local.scss b/packages/component-review/src/components/decision/DecisionLayout.local.scss index b6f5a99ea5f597101817dc3618b782f45ec3bf0d..c8832802e5f924b102c8cb1c6b6ffb42e21aa790 100644 --- a/packages/component-review/src/components/decision/DecisionLayout.local.scss +++ b/packages/component-review/src/components/decision/DecisionLayout.local.scss @@ -1,16 +1,16 @@ .root { + bottom: 0; display: flex; - position: absolute; - top: 50px; left: 0; - right: 0; - bottom: 0; overflow: hidden; + position: absolute; + right: 0; + top: 50px; } .column { + flex: 1; height: 100%; overflow-y: hidden; - flex: 1; padding: 10px; } diff --git a/packages/component-review/src/components/decision/DecisionReview.js b/packages/component-review/src/components/decision/DecisionReview.js index 46ab4bb844726faea2ecb8601714c19ecea37192..49b5faea12177acd7b8bbcced2c3cb450d63c108 100644 --- a/packages/component-review/src/components/decision/DecisionReview.js +++ b/packages/component-review/src/components/decision/DecisionReview.js @@ -11,31 +11,27 @@ const DecisionReview = ({ review, reviewer, journal, open, toggleOpen }) => ( className={classes.indicator} style={{ backgroundColor: review.recommendation - ? journal.recommendations.find(item => - item.value === review.recommendation + ? journal.recommendations.find( + item => item.value === review.recommendation, ).color - : 'black' - }}/> + : 'black', + }} + /> - <span className={classes.ordinal}> - Review {reviewer.ordinal} - </span> + <span className={classes.ordinal}>Review {reviewer.ordinal}</span> - <span className={classes.name}> - {reviewer.name || 'Anonymous'} - </span> + <span className={classes.name}>{reviewer.name || 'Anonymous'}</span> - <span className={classes.dots}/> + <span className={classes.dots} /> - <button - className={classes.toggle} - onClick={toggleOpen} - >{ open ? 'Hide' : 'Show' }</button> + <button className={classes.toggle} onClick={toggleOpen}> + {open ? 'Hide' : 'Show'} + </button> </div> {open && ( <div className={classes.review}> - <Review review={review}/> + <Review review={review} /> </div> )} </div> @@ -47,6 +43,6 @@ export default compose( withHandlers({ toggleOpen: props => () => { props.setOpen(open => !open) - } - }) + }, + }), )(DecisionReview) diff --git a/packages/component-review/src/components/decision/DecisionReview.local.scss b/packages/component-review/src/components/decision/DecisionReview.local.scss index 60c76579130ad420f6fc5191ec38c7f227429758..7261eeb9316308bc08c61ec13fd2ed49f308bb41 100644 --- a/packages/component-review/src/components/decision/DecisionReview.local.scss +++ b/packages/component-review/src/components/decision/DecisionReview.local.scss @@ -1,14 +1,14 @@ .heading { - display: flex; align-items: baseline; + display: flex; } .indicator { border-radius: 100%; display: inline-block; - width: 10px; height: 10px; margin-right: 10px; + width: 10px; } .ordinal { @@ -17,36 +17,36 @@ } .name { + background: white; font-family: var(--font-mono); margin-right: 10px; - background: white; &::after { + color: #aaa; + content: ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . "; float: left; font-size: 0.8em; - letter-spacing: -2px; - width: 0; font-weight: 400; - color: #aaa; + letter-spacing: -2px; white-space: nowrap; - content: ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . "; + width: 0; } } .dots { - flex: 1; background-color: #eee; + flex: 1; } .toggle { background: white; border: none; border-bottom: 2px solid transparent; - font-size: inherit; + color: var(--color-primary); cursor: pointer; - margin-left: 10px; + font-size: inherit; font-style: italic; - color: var(--color-primary); + margin-left: 10px; &:hover { border-bottom: 2px solid var(color-primary); diff --git a/packages/component-review/src/components/decision/DecisionReviews.js b/packages/component-review/src/components/decision/DecisionReviews.js index 75fed0d0a073995ff6b9363b11d052846d70cf75..659014093459125ac571728e33dccc965b8e5a47 100644 --- a/packages/component-review/src/components/decision/DecisionReviews.js +++ b/packages/component-review/src/components/decision/DecisionReviews.js @@ -7,16 +7,20 @@ import classes from './DecisionReviews.local.scss' const DecisionReviews = ({ journal, version }) => ( <div className={classes.root}> - {version.reviewers && version.reviewers - .filter(review => review.submitted) - .map((review, index) => ( - <div className={classes.review} key={review.id}> - <DecisionReview review={review} reviewer={{ - name: null, - ordinal: index + 1 - }}/> - </div> - ))} + {version.reviewers && + version.reviewers + .filter(review => review.submitted) + .map((review, index) => ( + <div className={classes.review} key={review.id}> + <DecisionReview + review={review} + reviewer={{ + name: null, + ordinal: index + 1, + }} + /> + </div> + ))} </div> ) diff --git a/packages/component-review/src/components/decision/DecisionReviews.local.scss b/packages/component-review/src/components/decision/DecisionReviews.local.scss index b83b098b9d214bf2904dec483d98c2ff78a54bc9..1b312ebb1bed1c12a08bb25895622a334898f14f 100644 --- a/packages/component-review/src/components/decision/DecisionReviews.local.scss +++ b/packages/component-review/src/components/decision/DecisionReviews.local.scss @@ -3,6 +3,6 @@ } .review:not(:last-child) { - margin-top: 20px; margin-bottom: 20px; + margin-top: 20px; } diff --git a/packages/component-review/src/components/metadata/ReviewMetadata.js b/packages/component-review/src/components/metadata/ReviewMetadata.js index 826b126a8f95808c19c0ec657a945b16c2d6047c..af1389da082468ce55f3291c6b50b1e3049bcb63 100644 --- a/packages/component-review/src/components/metadata/ReviewMetadata.js +++ b/packages/component-review/src/components/metadata/ReviewMetadata.js @@ -4,46 +4,39 @@ import classes from './ReviewMetadata.local.scss' const ReviewMetadata = ({ version, handlingEditors }) => ( <div> - <div className={classes.title}> - Metadata - </div> + <div className={classes.title}>Metadata</div> <table> <tbody> - <tr> - <th className={classes.heading}> - peer review: - </th> - <td> - {version.declarations.openReview ? 'open' : 'closed'} - </td> - </tr> - - {!!handlingEditors && ( <tr> - <th className={classes.heading}> - handling editor: - </th> - <td> - {handlingEditors.map(user => ( - <span key={user.username}>{user.username}</span> - ))} - </td> + <th className={classes.heading}>peer review:</th> + <td>{version.declarations.openReview ? 'open' : 'closed'}</td> </tr> - )} - {!!version.files.supplementary.length && ( - <tr> - <th className={classes.heading}> - {version.files.supplementary.length} supplementary {version.files.supplementary.length === 1 ? 'file' : 'files'}: - </th> - <td> - {version.files.supplementary.map(file => ( - <File key={file.url} value={file}/> - ))} - </td> - </tr> - )} + {!!handlingEditors && ( + <tr> + <th className={classes.heading}>handling editor:</th> + <td> + {handlingEditors.map(user => ( + <span key={user.username}>{user.username}</span> + ))} + </td> + </tr> + )} + + {!!version.files.supplementary.length && ( + <tr> + <th className={classes.heading}> + {version.files.supplementary.length} supplementary{' '} + {version.files.supplementary.length === 1 ? 'file' : 'files'}: + </th> + <td> + {version.files.supplementary.map(file => ( + <File key={file.url} value={file} /> + ))} + </td> + </tr> + )} </tbody> </table> </div> diff --git a/packages/component-review/src/components/metadata/ReviewMetadata.local.scss b/packages/component-review/src/components/metadata/ReviewMetadata.local.scss index 5ccec9444f16bdb71f76047a90012b0a30fdea8a..d729330c648090d7e08c87282541fac144b0eed1 100644 --- a/packages/component-review/src/components/metadata/ReviewMetadata.local.scss +++ b/packages/component-review/src/components/metadata/ReviewMetadata.local.scss @@ -7,17 +7,17 @@ table td { } .title { - font-weight: 400; border-bottom: 1px solid #222; + font-weight: 400; margin-bottom: 0.5em; } .heading { + color: #aaa; + font-style: italic; font-weight: 400; padding-bottom: 1em; + padding-right: 1em; text-align: left; vertical-align: top; - font-style: italic; - padding-right: 1em; - color: #aaa; } diff --git a/packages/component-review/src/components/review/Review.js b/packages/component-review/src/components/review/Review.js index 85882d7dddcd3264a9cd88b597cf03c90650e67c..d1dda9ad499301bafc2c04b428bce5bd54a371ba 100644 --- a/packages/component-review/src/components/review/Review.js +++ b/packages/component-review/src/components/review/Review.js @@ -6,45 +6,39 @@ import classes from './Review.local.scss' const Review = ({ review }) => ( <div> <div> - <div className={classes.heading}> - Note - </div> + <div className={classes.heading}>Note</div> <div className={classes.note}> <div className={classes.content}> - <NoteViewer value={review.note.content}/> + <NoteViewer value={review.note.content} /> </div> - {review.note.attachments - && review.note.attachments.map(attachment => ( - <Attachment key={attachment.url} value={attachment}/> - ))} + {review.note.attachments && + review.note.attachments.map(attachment => ( + <Attachment key={attachment.url} value={attachment} /> + ))} </div> </div> {review.confidential && ( <div> - <div className={classes.heading}> - Confidential - </div> + <div className={classes.heading}>Confidential</div> <div className={classes.note}> <div className={classes.content}> - <NoteViewer value={review.confidential.content}/> + <NoteViewer value={review.confidential.content} /> </div> - {review.confidential.attachments - && review.confidential.attachments.map(attachment => ( - <Attachment key={attachment.url} value={attachment}/> - ))} + {review.confidential.attachments && + review.confidential.attachments.map(attachment => ( + <Attachment key={attachment.url} value={attachment} /> + ))} </div> </div> )} <div> - <div className={classes.heading}> - Recommendation - </div> + <div className={classes.heading}>Recommendation</div> <div className={classes.recommendation}>{review.recommendation}</div> </div> diff --git a/packages/component-review/src/components/review/Review.local.scss b/packages/component-review/src/components/review/Review.local.scss index 1a588b648af6eb0eaefd9c52b446e2b3d1255ed4..e7c38e4e0945a0bb1e769d69ea54031ce48fd1ea 100644 --- a/packages/component-review/src/components/review/Review.local.scss +++ b/packages/component-review/src/components/review/Review.local.scss @@ -1,7 +1,7 @@ .heading { font-weight: bold; - margin-top: 20px; margin-bottom: 10px; + margin-top: 20px; } .note { diff --git a/packages/component-review/src/components/review/ReviewForm.js b/packages/component-review/src/components/review/ReviewForm.js index 00fa6cc0c2864923938108e6004b742412205ef6..0c4a38429ef1d502d06c6610817ddb425f812806 100644 --- a/packages/component-review/src/components/review/ReviewForm.js +++ b/packages/component-review/src/components/review/ReviewForm.js @@ -1,35 +1,35 @@ import React from 'react' import { FormSection } from 'redux-form' -import { Button } from 'xpub-ui' import { NoteEditor } from 'xpub-edit' -import { Attachments, RadioGroup, ValidatedField } from 'xpub-ui' +import { Attachments, Button, RadioGroup, ValidatedField } from 'xpub-ui' import { withJournal } from 'xpub-journal' import { required } from 'xpub-validators' import classes from './ReviewForm.local.scss' -const NoteInput = input => - <NoteEditor - title="Review" - placeholder="Enter your review…" - {...input}/> +const NoteInput = input => ( + <NoteEditor placeholder="Enter your review…" title="Review" {...input} /> +) -const AttachmentsInput = uploadFile => input => - <Attachments - uploadFile={uploadFile} - {...input}/> +const AttachmentsInput = uploadFile => input => ( + <Attachments uploadFile={uploadFile} {...input} /> +) -const ConfidentialInput = input => +const ConfidentialInput = input => ( <NoteEditor - title="Confidential" placeholder="Enter a confidential note to the editor (optional)…" - {...input}/> + title="Confidential" + {...input} + /> +) -const RecommendationInput = journal => input => +const RecommendationInput = journal => input => ( <RadioGroup - inline class={classes.class} + inline options={journal.recommendations} - {...input}/> + {...input} + /> +) const ReviewForm = ({ journal, valid, handleSubmit, uploadFile }) => ( <form onSubmit={handleSubmit}> @@ -38,14 +38,16 @@ const ReviewForm = ({ journal, valid, handleSubmit, uploadFile }) => ( <div className={classes.note}> <div className={classes.content}> <ValidatedField + component={NoteInput} name="content" validate={[required]} - component={NoteInput}/> + /> </div> <ValidatedField + component={AttachmentsInput(uploadFile)} name="attachments" - component={AttachmentsInput(uploadFile)}/> + /> </div> </FormSection> </div> @@ -54,30 +56,29 @@ const ReviewForm = ({ journal, valid, handleSubmit, uploadFile }) => ( <FormSection name="confidential"> <div className={classes.note}> <div className={classes.content}> - <ValidatedField - name="content" - component={ConfidentialInput}/> + <ValidatedField component={ConfidentialInput} name="content" /> </div> - <ValidatedField - name="attachments" - component={AttachmentsInput}/> + <ValidatedField component={AttachmentsInput} name="attachments" /> </div> </FormSection> </div> <div className={classes.section}> <FormSection name="Recommendation"> - <div className={classes.title}>Recommendation</div> + <div className={classes.title}>Recommendation</div> <ValidatedField + component={RecommendationInput(journal)} name="recommendation" validate={[required]} - component={RecommendationInput(journal)}/> + /> </FormSection> </div> <div> - <Button type="submit" primary disabled={!valid}>Submit</Button> + <Button disabled={!valid} primary type="submit"> + Submit + </Button> </div> </form> ) diff --git a/packages/component-review/src/components/review/ReviewForm.local.scss b/packages/component-review/src/components/review/ReviewForm.local.scss index 03f8a7b6128e90a5ba58fcf42ee799eca32e0ff4..fd0f7656346ca0eafd6954a7b83a99127e236079 100644 --- a/packages/component-review/src/components/review/ReviewForm.local.scss +++ b/packages/component-review/src/components/review/ReviewForm.local.scss @@ -3,8 +3,8 @@ --letter-spacing: 0; font-size: 1em; - margin-top: 4em; margin-bottom: 2em; + margin-top: 4em; } .note { @@ -18,6 +18,6 @@ .title { font-size: 1.5em; font-weight: 600; - margin-right: 10px; margin-bottom: 1em; + margin-right: 10px; } diff --git a/packages/component-review/src/components/review/ReviewLayout.js b/packages/component-review/src/components/review/ReviewLayout.js index 371bf371c3157f34914647a055fcfb9be6768abd..2c762bab596f251dcc4888375c47a8132d89c365 100644 --- a/packages/component-review/src/components/review/ReviewLayout.js +++ b/packages/component-review/src/components/review/ReviewLayout.js @@ -8,12 +8,23 @@ import Review from './Review' import Tabs from '../tabs/Tabs' import classes from './ReviewLayout.local.scss' -const ReviewLayout = ({ project, versions, currentVersion, handlingEditors, reviewer, valid, handleSubmit, uploadFile }) => { +const ReviewLayout = ({ + project, + versions, + currentVersion, + handlingEditors, + reviewer, + valid, + handleSubmit, + uploadFile, +}) => { const reviewSections = [] const editorSections = [] versions.forEach(version => { - const review = version.reviewers.find(review => review.reviewer === reviewer.id) + const review = version.reviewers.find( + review => review.reviewer === reviewer.id, + ) if (review && review.submitted) { const submittedMoment = moment(review.submitted) @@ -21,33 +32,32 @@ const ReviewLayout = ({ project, versions, currentVersion, handlingEditors, revi const label = submittedMoment.format('YYYY-MM-DD') reviewSections.push({ - key, - label, content: ( <div> <ReviewMetadata + handlingEditors={handlingEditors} version={version} - handlingEditors={handlingEditors}/> - <Review - review={review}/> + /> + <Review review={review} /> </div> ), + key, + label, }) // TODO: need to include unreviewed versions? editorSections.push({ + content: ( + <SimpleEditor content={version.source} layout="bare" readOnly /> + ), key, label, - content: <SimpleEditor - content={version.source} - layout="bare" - readOnly={true}/> }) } }, []) const review = currentVersion.reviewers.find( - review => review.reviewer === reviewer.id + review => review.reviewer === reviewer.id, ) if (!review || !review.submitted) { @@ -56,29 +66,30 @@ const ReviewLayout = ({ project, versions, currentVersion, handlingEditors, revi const label = submittedMoment.format('YYYY-MM-DD') reviewSections.push({ - key, - label, content: ( <div> <ReviewMetadata + handlingEditors={handlingEditors} version={currentVersion} - handlingEditors={handlingEditors}/> + /> <ReviewForm + handleSubmit={handleSubmit} review={review} + uploadFile={uploadFile} valid={valid} - handleSubmit={handleSubmit} - uploadFile={uploadFile}/> + /> </div> - ) + ), + key, + label, }) editorSections.push({ + content: ( + <SimpleEditor content={currentVersion.source} layout="bare" readOnly /> + ), key, label, - content: <SimpleEditor - layout="bare" - content={currentVersion.source} - readOnly={true}/> }) } @@ -86,16 +97,18 @@ const ReviewLayout = ({ project, versions, currentVersion, handlingEditors, revi <div className={classes.root}> <div className={classes.manuscript}> <Tabs - sections={editorSections} activeKey={editorSections[editorSections.length - 1].key} - title="Versions"/> + sections={editorSections} + title="Versions" + /> </div> <div className={classes.review}> <Tabs - sections={reviewSections} activeKey={reviewSections[reviewSections.length - 1].key} - title="Versions"/> + sections={reviewSections} + title="Versions" + /> </div> </div> ) diff --git a/packages/component-review/src/components/review/ReviewLayout.local.scss b/packages/component-review/src/components/review/ReviewLayout.local.scss index 4cd0d2b0f67bb99a6ebb5b0721a9d2fd9677db5c..434027f7563be5f83da18e4b737509b8b9a17abb 100644 --- a/packages/component-review/src/components/review/ReviewLayout.local.scss +++ b/packages/component-review/src/components/review/ReviewLayout.local.scss @@ -1,9 +1,9 @@ .root { display: grid; + grid-column-gap: 2em; grid-template-areas: "manuscript review files"; grid-template-columns: minmax(200px, 80ch) minmax(200px, 50ch) minmax(10ch, 10ch); justify-content: center; - grid-column-gap: 2em; } .manuscript { @@ -15,8 +15,8 @@ } .files { - position: absolute; margin-left: 4em; + position: absolute; } .attach { diff --git a/packages/component-review/src/components/reviewers/Reviewer.js b/packages/component-review/src/components/reviewers/Reviewer.js index 07e9091f92f8f75331b0231b876734a4f83b41cc..8ecc11ca0062d0e279fa0535c1bedff88e97f254 100644 --- a/packages/component-review/src/components/reviewers/Reviewer.js +++ b/packages/component-review/src/components/reviewers/Reviewer.js @@ -1,24 +1,22 @@ import React from 'react' import { map } from 'lodash' import Moment from 'react-moment' -import classes from './Reviewer.local.scss' import { Avatar, Button } from 'xpub-ui' -const ordinalLetter = ordinal => { - return ordinal ? String.fromCharCode(96 + ordinal) : null -} +import classes from './Reviewer.local.scss' + +const ordinalLetter = ordinal => + ordinal ? String.fromCharCode(96 + ordinal) : null const Reviewer = ({ reviewer, removeReviewer }) => ( <div className={classes.root}> <Avatar - status={reviewer.status} - width={100} height={70} reviewerLetter={ordinalLetter(reviewer._reviewer.ordinal)} + status={reviewer.status} + width={100} /> - <div className={classes.name}> - {reviewer._user.username} - </div> + <div className={classes.name}>{reviewer._user.username}</div> <div> {map(reviewer.events, (event, key) => ( <div className={classes.date} key={`${key}-${event}`}> diff --git a/packages/component-review/src/components/reviewers/Reviewer.local.scss b/packages/component-review/src/components/reviewers/Reviewer.local.scss index 6cca2c0a7a7818877a9adb9ceb6e5d1bc854e560..703e48919ce3d3e56a3d7338beba482bb6f49493 100644 --- a/packages/component-review/src/components/reviewers/Reviewer.local.scss +++ b/packages/component-review/src/components/reviewers/Reviewer.local.scss @@ -1,34 +1,34 @@ .root { color: #333; display: inline-block; - padding: 10px; + font-family: var(--font-reviewer); margin-bottom: 10px; margin-right: 10px; - font-family: var(--font-reviewer); + padding: 10px; } .name { color: current-color; - font-size: 18px; font-family: var(--font-interface); + font-size: 18px; font-weight: 600; } .fullname { color: current-color; font-size: 1.3em; - margin-top: 0.2em; - font-weight: bold; font-style: italic; + font-weight: bold; + margin-top: 0.2em; } .date { color: current-color; font-family: var(--font-interface); - font-style: italic; font-size: 0.9em; - margin-top: 0.4em; + font-style: italic; margin-left: 0.1em; + margin-top: 0.4em; } .root button { diff --git a/packages/component-review/src/components/reviewers/ReviewerContainer.js b/packages/component-review/src/components/reviewers/ReviewerContainer.js index 9e92ea9dc196da142d69f279a65452a04b6782f7..f3ec7eb0c140c074a69d69f53b96d332165aa887 100644 --- a/packages/component-review/src/components/reviewers/ReviewerContainer.js +++ b/packages/component-review/src/components/reviewers/ReviewerContainer.js @@ -4,16 +4,16 @@ import { actions } from 'pubsweet-client' import Reviewer from './Reviewer' const removeReviewer = props => () => { - const id = props.reviewer.id + const { id } = props.reviewer return props.deleteFragment(props.project, { id }) } export default compose( connect(null, { - deleteFragment: actions.deleteFragment + deleteFragment: actions.deleteFragment, }), withHandlers({ - removeReviewer: props => removeReviewer(props) - }) + removeReviewer: props => removeReviewer(props), + }), )(Reviewer) diff --git a/packages/component-review/src/components/reviewers/ReviewerForm.js b/packages/component-review/src/components/reviewers/ReviewerForm.js index 4de805cc24dfadb6c4ec02cc21cb63a8f0d6af9c..6a94db20a78ebe5cadc2ea7d896890ccdda4aaf1 100644 --- a/packages/component-review/src/components/reviewers/ReviewerForm.js +++ b/packages/component-review/src/components/reviewers/ReviewerForm.js @@ -16,25 +16,34 @@ const OptionRenderer = option => ( const ReviewerInput = loadOptions => ({ input }) => ( <Select.AsyncCreatable {...input} - valueKey="id" - labelKey="username" + // autoload={false} filterOption={() => true} + labelKey="username" loadOptions={loadOptions} - promptTextCreator={label => `Add ${label}?`} optionRenderer={OptionRenderer} - // autoload={false} + promptTextCreator={label => `Add ${label}?`} + valueKey="id" /> ) -const ReviewerForm = ({ reset, valid, handleSubmit, onSubmit, loadOptions }) => ( +const ReviewerForm = ({ + reset, + valid, + handleSubmit, + onSubmit, + loadOptions, +}) => ( <form onSubmit={handleSubmit(onSubmit(reset))}> <Field + component={ReviewerInput(loadOptions)} name="user" validate={required} - component={ReviewerInput(loadOptions)}/> + /> <div className={classes.actions}> - <Button type="submit" primary disabled={!valid}>Invite reviewer</Button> + <Button disabled={!valid} primary type="submit"> + Invite reviewer + </Button> </div> </form> ) diff --git a/packages/component-review/src/components/reviewers/ReviewerForm.local.scss b/packages/component-review/src/components/reviewers/ReviewerForm.local.scss index 27de25aec088fcb97e401139bd0f505a059f5c7a..99fc6ae9980249d3f746726c727e472f606d9cce 100644 --- a/packages/component-review/src/components/reviewers/ReviewerForm.local.scss +++ b/packages/component-review/src/components/reviewers/ReviewerForm.local.scss @@ -1,10 +1,10 @@ .actions { - margin-top: 10px; color: red; + margin-top: 10px; } .root { background: red; } -// look at http://agutoli.github.io/ and https://www.npmjs.com/package/react-styled-select as an alternative for react-select +// look at http://agutoli.github.io/ and https://www.npmjs.com/package/react-styled-select as an alternative for react-select diff --git a/packages/component-review/src/components/reviewers/ReviewerFormContainer.js b/packages/component-review/src/components/reviewers/ReviewerFormContainer.js index 30e2a2199f08194c68b59b1e382920777568d594..da8aa28b6ea1aa64fcbe09a1f88b389ceb3ab42e 100644 --- a/packages/component-review/src/components/reviewers/ReviewerFormContainer.js +++ b/packages/component-review/src/components/reviewers/ReviewerFormContainer.js @@ -15,44 +15,49 @@ const getProjectReviewer = (props, user) => { const addProjectReviewer = (props, user) => { const reviewer = { id: uuid(), - user: user.id + user: user.id, } - return props.updateProject({ - id: props.project.id, - rev: props.project.rev, - reviewers: (props.project.reviewers || []).concat(reviewer) - }).then(() => reviewer) + return props + .updateProject({ + id: props.project.id, + rev: props.project.rev, + reviewers: (props.project.reviewers || []).concat(reviewer), + }) + .then(() => reviewer) } const addReviewer = (props, projectReviewer) => { const reviewer = { + events: { + invited: new Date().toString(), + }, id: uuid(), reviewer: projectReviewer.id, status: 'invited', - events: { - invited: (new Date()).toString() - } } - return props.updateVersion(props.project, { - id: props.version.id, - rev: props.version.rev, - reviewers: (props.version.reviewers || []).concat(reviewer) - }).then(() => reviewer) + return props + .updateVersion(props.project, { + id: props.version.id, + rev: props.version.rev, + reviewers: (props.version.reviewers || []).concat(reviewer), + }) + .then(() => reviewer) } -const handleSubmit = props => reset => values => { +const handleSubmit = props => reset => values => // TODO: create a user account if values.user.id is null - return getProjectReviewer(props, values.user).then(projectReviewer => { - if (some(props.version.reviewers, { reviewer: projectReviewer.id })) { - throw new SubmissionError('This reviewer has already been added') - } + getProjectReviewer(props, values.user) + .then(projectReviewer => { + if (some(props.version.reviewers, { reviewer: projectReviewer.id })) { + throw new SubmissionError('This reviewer has already been added') + } - return addReviewer(props, projectReviewer) - }).then(() => reset()) -} + return addReviewer(props, projectReviewer) + }) + .then(() => reset()) const loadOptions = props => input => { const options = props.reviewerUsers @@ -74,6 +79,6 @@ export default compose( onSubmit: props => handleSubmit(props), }), reduxForm({ - form: 'reviewers' - }) + form: 'reviewers', + }), )(ReviewerForm) diff --git a/packages/component-review/src/components/reviewers/Reviewers.js b/packages/component-review/src/components/reviewers/Reviewers.js index c59746d5af31ac6752d9750936583b240ede616d..923c82ed35b5d466f6bd3c92d6b4ed239097d57a 100644 --- a/packages/component-review/src/components/reviewers/Reviewers.js +++ b/packages/component-review/src/components/reviewers/Reviewers.js @@ -1,22 +1,27 @@ import React from 'react' import classes from './Reviewers.local.scss' -const Reviewers = ({ ReviewerForm, Reviewer, project, version, reviewers, reviewerUsers }) => ( +const Reviewers = ({ + ReviewerForm, + Reviewer, + project, + version, + reviewers, + reviewerUsers, +}) => ( <div className={classes.root}> <div className={classes.form}> <ReviewerForm project={project} + reviewerUsers={reviewerUsers} version={version} - reviewerUsers={reviewerUsers}/> + /> </div> {reviewers && ( <div className={classes.reviewers}> {reviewers.map(reviewer => ( - <Reviewer - key={reviewer.id} - project={project} - reviewer={reviewer}/> + <Reviewer key={reviewer.id} project={project} reviewer={reviewer} /> ))} </div> )} diff --git a/packages/component-review/src/components/reviewers/Reviewers.local.scss b/packages/component-review/src/components/reviewers/Reviewers.local.scss index 0365b0fffa1e2aaee169758496499cf5859c2094..5023eff71a3af6557ee2c5de35eab55db24bb091 100644 --- a/packages/component-review/src/components/reviewers/Reviewers.local.scss +++ b/packages/component-review/src/components/reviewers/Reviewers.local.scss @@ -7,8 +7,8 @@ } .reviewers { - flex: 1; - padding: 20px; display: flex; + flex: 1; flex-wrap: wrap; + padding: 20px; } diff --git a/packages/component-review/src/components/tabs/Tab.js b/packages/component-review/src/components/tabs/Tab.js index ed3c46902bc19a39bc806895456decc8564b748a..d54f5d35c2d7affc20258bc985af7a60b90c8260 100644 --- a/packages/component-review/src/components/tabs/Tab.js +++ b/packages/component-review/src/components/tabs/Tab.js @@ -1,11 +1,16 @@ +import classnames from 'classnames' import React from 'react' + import classes from './Tab.local.scss' -import classnames from 'classnames' const Tab = ({ active, children }) => ( - <div className={classnames(classes.root, { - [classes.active]: active - })}>{children}</div> + <div + className={classnames(classes.root, { + [classes.active]: active, + })} + > + {children} + </div> ) export default Tab diff --git a/packages/component-review/src/components/tabs/Tab.local.scss b/packages/component-review/src/components/tabs/Tab.local.scss index 1848b102cf3a3d222dd80aa3ed9babe28bf24cc8..32ca7a4465f56a41d73b172e953f4c49c3eb870a 100644 --- a/packages/component-review/src/components/tabs/Tab.local.scss +++ b/packages/component-review/src/components/tabs/Tab.local.scss @@ -1,15 +1,28 @@ .root { - display: inline-block; - padding: 5px; - color: #aaa; border-color: inherit; border-style: solid; border-width: 0 0 1px; + color: #aaa; cursor: pointer; - position: relative; + display: inline-block; font-size: 0.8em; margin-left: 1em; + padding: 5px; padding-left: 1.2em; + position: relative; +} + +.root::after { + background: white; + border-bottom: 1px solid #aaa; + bottom: -2px; + content: " "; + display: block; + position: absolute; + right: -25px; + transform: rotate(-66deg); + transform-origin: 0% 0%; + width: 25px; } .root:hover { @@ -28,19 +41,6 @@ } } -.root::after { - content: " "; - width: 25px; - display: block; - border-bottom: 1px solid #aaa; - position: absolute; - right: -25px; - bottom: -2px; - background: white; - transform: rotate(-66deg); - transform-origin: 0% 0%; -} - .root.editor-wrapper { height: 100%; } diff --git a/packages/component-review/src/components/tabs/Tabs.js b/packages/component-review/src/components/tabs/Tabs.js index c1e1dcc07fd9de48f1e0ee65a0e05f7046930edd..19493a37b7aa766c7df2955707c0e428af715386 100644 --- a/packages/component-review/src/components/tabs/Tabs.js +++ b/packages/component-review/src/components/tabs/Tabs.js @@ -5,21 +5,21 @@ import classes from './Tabs.local.scss' // TODO: allow the tab content to be separate from the key class Tabs extends React.Component { - constructor (props) { + constructor(props) { super(props) this.state = { - activeKey: null + activeKey: null, } } - componentDidMount () { + componentDidMount() { const { activeKey } = this.props this.setState({ activeKey }) } - componentWillReceiveProps (nextProps) { + componentWillReceiveProps(nextProps) { const { activeKey } = nextProps if (activeKey !== this.props.activeKey) { @@ -27,27 +27,26 @@ class Tabs extends React.Component { } } - setActiveKey = activeKey => this.setState({ activeKey }) + setActiveKey(activeKey) { + this.setState({ activeKey }) + } - render () { + render() { const { sections, title } = this.props const { activeKey } = this.state return ( <div className={classes.root}> <div className={classes.tabs}> - {title && ( - <span className={classes.title}>{title}</span> - )} + {title && <span className={classes.title}>{title}</span>} {sections.map(({ key, label }) => ( <span - key={key} className={classes.tab} - onClick={() => this.setActiveKey(key)}> - <Tab active={activeKey === key}> - {label || key} - </Tab> + key={key} + onClick={() => this.setActiveKey(key)} + > + <Tab active={activeKey === key}>{label || key}</Tab> </span> ))} </div> diff --git a/packages/component-review/src/components/tabs/Tabs.local.scss b/packages/component-review/src/components/tabs/Tabs.local.scss index e9ccb6cbf25ce1f003593f196ea3e0df99cafa36..ebee3e28e9be0b15fc0d8c39da7a0e6997a08074 100644 --- a/packages/component-review/src/components/tabs/Tabs.local.scss +++ b/packages/component-review/src/components/tabs/Tabs.local.scss @@ -1,29 +1,29 @@ .root { - position: relative; - height: 100%; - overflow-y: hidden; display: flex; flex-direction: column; + height: 100%; + overflow-y: hidden; + position: relative; } .tabs { + align-items: baseline; display: flex; flex-wrap: wrap; - padding: 10px; margin-bottom: 10px; - align-items: baseline; + padding: 10px; } .title { - font-weight: 400; border-bottom: 1px solid #aaa; + font-weight: 400; + margin-right: -2.5em; padding-bottom: 4px; padding-right: 2em; - margin-right: -2.5em; } .content { - padding: 10px; flex: 1; // overflow-y: auto; + padding: 10px; } diff --git a/packages/component-review/src/index.js b/packages/component-review/src/index.js index 0225ff41f4787662ca6fbc4ecc49c3894f11810c..6f1f42a64b1ecf4a71345e76fa416d89015cb96c 100644 --- a/packages/component-review/src/index.js +++ b/packages/component-review/src/index.js @@ -1,7 +1,5 @@ module.exports = { frontend: { - components: [ - () => require('./components') - ] - } + components: [() => require('./components')], + }, } diff --git a/packages/component-review/styleguide.config.js b/packages/component-review/styleguide.config.js index f618a3a06d64a6328310e97380785dbed0cfca36..e77fe9f19605fbf9e420ab1a4a6a73db97d0633c 100644 --- a/packages/component-review/styleguide.config.js +++ b/packages/component-review/styleguide.config.js @@ -1,42 +1,44 @@ module.exports = { title: 'xpub review style guide', styleguideComponents: { - StyleGuideRenderer: require.resolve('xpub-styleguide/src/components/StyleGuideRenderer'), - Wrapper: require.resolve('xpub-styleguide/src/components/Wrapper') + StyleGuideRenderer: require.resolve( + 'xpub-styleguide/src/components/StyleGuideRenderer', + ), + Wrapper: require.resolve('xpub-styleguide/src/components/Wrapper'), }, context: { - faker: 'faker' + faker: 'faker', }, skipComponentsWithoutExample: true, serverPort: 6065, theme: { fontFamily: { - base: '"Fira Sans", sans-serif' + base: '"Fira Sans", sans-serif', }, color: { - link: 'cornflowerblue' - } + link: 'cornflowerblue', + }, }, sections: [ { name: 'Reviewers', - components: 'src/components/reviewers/*.js' + components: 'src/components/reviewers/*.js', }, { name: 'Review', - components: 'src/components/review/*.js' + components: 'src/components/review/*.js', }, { name: 'Decision', - components: 'src/components/decision/*.js' + components: 'src/components/decision/*.js', }, { name: 'Metadata', - components: 'src/components/metadata/*.js' + components: 'src/components/metadata/*.js', }, { name: 'Tabs', - components: 'src/components/tabs/*.js' - } - ] + components: 'src/components/tabs/*.js', + }, + ], } diff --git a/packages/component-submit/src/components/Confirm.js b/packages/component-submit/src/components/Confirm.js index aa15e9a2d77d85d79e2e6f5f98426f61f2f6e5c9..80042aec6990bff5913ebcdf806515bfa9ad71bb 100644 --- a/packages/component-submit/src/components/Confirm.js +++ b/packages/component-submit/src/components/Confirm.js @@ -9,18 +9,42 @@ const Confirm = ({ toggleConfirming }) => ( By submitting the manuscript, you agree to the following statements. </h1> - <p>The corresponding author confirms that all co-authors are included, and that everyone listed as a co-author agrees to that role and all the following requirements and acknowledgements.</p> - - <p>The submission represents original work and that sources are given proper attribution. (The journal employs <a href="https://www.crossref.org/services/similarity-check/" target="_blank" rel="noopener noreferrer">CrossCheck</a> to compare submissions against a large and growing database of published scholarly content. If in the judgment of a senior editor a submission is genuinely suspected of plagiarism, it will be returned to the author(s) with a request for explanation.)</p> + <p> + The corresponding author confirms that all co-authors are included, and + that everyone listed as a co-author agrees to that role and all the + following requirements and acknowledgements. + </p> + + <p> + The submission represents original work and that sources are given + proper attribution. (The journal employs{' '} + <a + href="https://www.crossref.org/services/similarity-check/" + rel="noopener noreferrer" + target="_blank" + > + CrossCheck + </a>{' '} + to compare submissions against a large and growing database of published + scholarly content. If in the judgment of a senior editor a submission is + genuinely suspected of plagiarism, it will be returned to the author(s) + with a request for explanation.) + </p> <p>The research was conducted in accordance with ethical principles.</p> - <p>There is a Data Accessibility Statement, containing information about the location of open data and materials, in the manuscript.</p> + <p> + There is a Data Accessibility Statement, containing information about + the location of open data and materials, in the manuscript. + </p> - <p>A conflict of interest statement is present in the manuscript, even if to state no conflicts of interest.</p> + <p> + A conflict of interest statement is present in the manuscript, even if + to state no conflicts of interest. + </p> <div className={classes.actions}> - <Button type="submit" primary> + <Button primary type="submit"> Submit your manuscript </Button> <span className={classes.actionDivider}> or </span> diff --git a/packages/component-submit/src/components/Confirm.local.scss b/packages/component-submit/src/components/Confirm.local.scss index 5fe0855233976bcc71b45213fbd621cda18da2db..9d5595fd31257a8934026662cf8909d6fad8ea6a 100644 --- a/packages/component-submit/src/components/Confirm.local.scss +++ b/packages/component-submit/src/components/Confirm.local.scss @@ -1,17 +1,17 @@ .root { - max-width: 60em; - padding: 4rem; background: white; - max-height: 100%; - overflow-y: auto; color: #404040; line-height: 1.55; + max-height: 100%; + max-width: 60em; + overflow-y: auto; + padding: 4rem; } .root p { - width: 55ch; font-size: 1em; margin-bottom: 1.6em; + width: 55ch; } .heading { diff --git a/packages/component-submit/src/components/Declarations.js b/packages/component-submit/src/components/Declarations.js index 2750835d52170a1879f38aa92147cd23f7b848a4..55497f1aa7cd21512edfacba8d804f9ac3ec2771 100644 --- a/packages/component-submit/src/components/Declarations.js +++ b/packages/component-submit/src/components/Declarations.js @@ -6,31 +6,27 @@ import { withJournal } from 'xpub-journal' import { required } from 'xpub-validators' import classes from './Declarations.local.scss' -const DeclarationInput = input => ( - <YesOrNo inline={true} {...input}/> -) +const DeclarationInput = input => <YesOrNo inline {...input} /> -const Declarations = ({ journal }) => { - return ( - <FormSection name="declarations"> - {journal.declarations.questions.map(question => ( - <div - key={question.id} - id={`declarations.${question.id}`} - className={classnames(classes.section, classes.spread)}> - <div className={classes.legend}> - {question.legend} - </div> +const Declarations = ({ journal }) => ( + <FormSection name="declarations"> + {journal.declarations.questions.map(question => ( + <div + className={classnames(classes.section, classes.spread)} + id={`declarations.${question.id}`} + key={question.id} + > + <div className={classes.legend}>{question.legend}</div> - <ValidatedField - name={question.id} - required - validate={[required]} - component={DeclarationInput}/> - </div> - ))} - </FormSection> - ) -} + <ValidatedField + component={DeclarationInput} + name={question.id} + required + validate={[required]} + /> + </div> + ))} + </FormSection> +) export default withJournal(Declarations) diff --git a/packages/component-submit/src/components/Declarations.local.scss b/packages/component-submit/src/components/Declarations.local.scss index d46f2f9df41cd50a227cc2b228871aa02a2bdfc6..e1ee5ea85aa7bdc155434077b4c4724d400c31e7 100644 --- a/packages/component-submit/src/components/Declarations.local.scss +++ b/packages/component-submit/src/components/Declarations.local.scss @@ -8,8 +8,8 @@ } .legend { - font-weight: 600; font-size: 1em; + font-weight: 600; } .spread:hover { diff --git a/packages/component-submit/src/components/Metadata.js b/packages/component-submit/src/components/Metadata.js index 342ae91c951098696849d4604a452fd62c2a8d4e..4702c8536eab21a86adba3cd5ed8354cf7dffa9b 100644 --- a/packages/component-submit/src/components/Metadata.js +++ b/packages/component-submit/src/components/Metadata.js @@ -3,8 +3,16 @@ import { FormSection } from 'redux-form' import { AbstractEditor, TitleEditor } from 'xpub-edit' import { CheckboxGroup, Menu, TextField, ValidatedField } from 'xpub-ui' import { withJournal } from 'xpub-journal' +import { + join, + required, + minChars, + maxChars, + minSize, + split, +} from 'xpub-validators' + import classes from './Metadata.local.scss' -import { join, required, minChars, maxChars, minSize, split } from 'xpub-validators' const minSize1 = minSize(1) const minChars20 = minChars(20) @@ -12,98 +20,100 @@ const minChars100 = minChars(100) const maxChars500 = maxChars(500) const maxChars5000 = maxChars(5000) -const TitleInput = input => - <TitleEditor - placeholder="Enter the title…" - title="Title" - {...input}/> +const TitleInput = input => ( + <TitleEditor placeholder="Enter the title…" title="Title" {...input} /> +) -const AbstractInput = input => +const AbstractInput = input => ( <AbstractEditor - title="Abstract" placeholder="Enter the abstract…" - {...input}/> + title="Abstract" + {...input} + /> +) -const AuthorsInput = input => - <TextField - placeholder="Enter author names…" - {...input}/> +const AuthorsInput = input => ( + <TextField placeholder="Enter author names…" {...input} /> +) -const KeywordsInput = input => - <TextField - placeholder="Enter keywords…" - {...input}/> +const KeywordsInput = input => ( + <TextField placeholder="Enter keywords…" {...input} /> +) -const ArticleTypeInput = journal => input => - <Menu - options={journal.articleTypes} - {...input}/> +const ArticleTypeInput = journal => input => ( + <Menu options={journal.articleTypes} {...input} /> +) -const ArticleSectionInput = journal => input => - <CheckboxGroup - options={journal.articleSections} - {...input}/> +const ArticleSectionInput = journal => input => ( + <CheckboxGroup options={journal.articleSections} {...input} /> +) const Metadata = ({ journal }) => ( <FormSection name="metadata"> <div className={classes.section} id="metadata.title"> <ValidatedField + component={TitleInput} name="title" required validate={[minChars20, maxChars500]} - component={TitleInput}/> + /> </div> <div className={classes.section} id="metadata.abstract"> <ValidatedField + component={AbstractInput} name="abstract" required validate={[minChars100, maxChars5000]} - component={AbstractInput}/> + /> </div> <div className={classes.section} id="metadata.authors"> <div className={classes.label}>Authors</div> <ValidatedField - name="authors" - required + component={AuthorsInput} format={join()} + name="authors" parse={split()} + required validate={[minSize1]} - component={AuthorsInput}/> + /> </div> <div className={classes.section} id="metadata.keywords"> <div className={classes.label}>Keywords</div> <ValidatedField - name="keywords" - required + component={KeywordsInput} format={join()} + name="keywords" parse={split()} + required validate={[minSize1]} - component={KeywordsInput}/> + /> </div> <div className={classes.section} id="metadata.articleType"> <div className={classes.label}>Type of article</div> <ValidatedField + component={ArticleTypeInput(journal)} name="articleType" required validate={[required]} - component={ArticleTypeInput(journal)}/> + /> </div> <div className={classes.section} id="metadata.articleSection"> <div className={classes.label}>Section</div> <ValidatedField + component={ArticleSectionInput(journal)} name="articleSection" required validate={[required]} - component={ArticleSectionInput(journal)}/> + /> </div> </FormSection> ) diff --git a/packages/component-submit/src/components/Notes.js b/packages/component-submit/src/components/Notes.js index dbe2b548216f242a78d82f796d3cabbfecf06198..3dd379f8a38cd2422dc4bfd517b9809c6523c3f3 100644 --- a/packages/component-submit/src/components/Notes.js +++ b/packages/component-submit/src/components/Notes.js @@ -5,31 +5,37 @@ import { ValidatedField } from 'xpub-ui' import { required } from 'xpub-validators' import classes from './Metadata.local.scss' -const FundingInput = input => +const FundingInput = input => ( <NoteEditor placeholder="Enter an acknowledgment…" title="Funding body acknowledgement (required)" - {...input}/> + {...input} + /> +) -const InstructionsInput = input => +const InstructionsInput = input => ( <NoteEditor placeholder="Enter instructions for the editor…" title="Special instructions (confidential)" - {...input}/> + {...input} + /> +) const Notes = () => ( <FormSection name="notes"> <div className={classes.section} id="notes.fundingAcknowledgement"> <ValidatedField + component={FundingInput} name="fundingAcknowledgement" validate={[required]} - component={FundingInput}/> + /> </div> <div className={classes.section} id="notes.specialInstructions"> <ValidatedField + component={InstructionsInput} name="specialInstructions" - component={InstructionsInput}/> + /> </div> </FormSection> ) diff --git a/packages/component-submit/src/components/Submit.js b/packages/component-submit/src/components/Submit.js index 2fdfdad9275923b5dc9d50903bdbe35effe3e125..d1bbe7c2ce562a17cec3bf6adebddde3edbdee5d 100644 --- a/packages/component-submit/src/components/Submit.js +++ b/packages/component-submit/src/components/Submit.js @@ -11,48 +11,62 @@ import Confirm from './Confirm' // import Validots from './Validots' import classes from './Submit.local.scss' -const Submit = ({ project, version, valid, error, handleSubmit, uploadFile, confirming, toggleConfirming }) => ( - <div className={classnames(classes.root, { - [classes.confirming]: confirming - })}> - <div className={classes.title}> - Submission information - </div> +const Submit = ({ + project, + version, + valid, + error, + handleSubmit, + uploadFile, + confirming, + toggleConfirming, +}) => ( + <div + className={classnames(classes.root, { + [classes.confirming]: confirming, + })} + > + <div className={classes.title}>Submission information</div> <div className={classes.intro}> - <div>We have ingested your manuscript. To access your manuscript in an editor, please <Link to={`/projects/${project.id}/versions/${version.id}/manuscript`}>view here</Link>.</div> - <div>To complete your submission, please answer the following questions.</div> + <div> + We have ingested your manuscript. To access your manuscript in an + editor, please{' '} + <Link to={`/projects/${project.id}/versions/${version.id}/manuscript`}> + view here + </Link>. + </div> + <div> + To complete your submission, please answer the following questions. + </div> <div>The answers will be automatically saved.</div> </div> <form onSubmit={handleSubmit}> - <Metadata/> - <Declarations/> - <Suggestions/> - <Notes/> - <SupplementaryFiles uploadFile={uploadFile}/> + <Metadata /> + <Declarations /> + <Suggestions /> + <Notes /> + <SupplementaryFiles uploadFile={uploadFile} /> <div> - <Button - type="button" - primary - onClick={toggleConfirming}> + <Button onClick={toggleConfirming} primary type="button"> Submit your manuscript </Button> </div> {confirming && ( <div className={classes.confirm}> - <Confirm toggleConfirming={toggleConfirming}/> + <Confirm toggleConfirming={toggleConfirming} /> </div> )} </form> - {/*<div className={classes.validots}> + {/* <div className={classes.validots}> <Validots valid={valid} handleSubmit={handleSubmit}/> - </div>*/} + </div> */} </div> ) diff --git a/packages/component-submit/src/components/Submit.local.scss b/packages/component-submit/src/components/Submit.local.scss index 620e814447c4eb9b474e8b4328663945a5675022..07d657b06b1bb804c5b22304aa01a1bb9a28cadd 100644 --- a/packages/component-submit/src/components/Submit.local.scss +++ b/packages/component-submit/src/components/Submit.local.scss @@ -1,8 +1,8 @@ .root { - max-width: 60em; - margin: auto; font-family: var(--font-interface); line-height: 1.3; + margin: auto; + max-width: 60em; } .title { @@ -18,20 +18,20 @@ a { color: var(--color-primary); - text-decoration: underline; font-style: italic; + text-decoration: underline; } .confirm { - position: fixed; - top: 0; - right: 0; + align-items: center; + background: rgba(255, 255, 255, 0.95); bottom: 0; - left: 0; display: flex; - align-items: center; justify-content: center; - background: rgba(255, 255, 255, 0.95); + left: 0; + position: fixed; + right: 0; + top: 0; } .confirming { @@ -40,8 +40,8 @@ a { .validots { position: absolute; - top: 50px; right: 10px; + top: 50px; } a:visited { diff --git a/packages/component-submit/src/components/SubmitPage.js b/packages/component-submit/src/components/SubmitPage.js index b484e898150d21506c50dac281d86ec3b0f197dc..5102acb77cdc205db1562d57072dc2dc8d2471c3 100644 --- a/packages/component-submit/src/components/SubmitPage.js +++ b/packages/component-submit/src/components/SubmitPage.js @@ -8,33 +8,39 @@ import { ConnectPage } from 'xpub-connect' import { selectCollection, selectFragment } from 'xpub-selectors' import Submit from './Submit' -const onSubmit = (values, dispatch, { history, project, version }) => { +const onSubmit = (values, dispatch, { history, project, version }) => // console.log('submit', values) - return dispatch(actions.updateFragment(project, { - id: version.id, - rev: version.rev, - submitted: new Date(), - ...values - })).then(() => { - return dispatch(actions.updateCollection({ - id: project.id, - rev: project.rev, - status: 'submitted' - })) - }).then(() => { - history.push('/') - }).catch(error => { - if (error.validationErrors) { - throw new SubmissionError() - } - }) -} + dispatch( + actions.updateFragment(project, { + id: version.id, + rev: version.rev, + submitted: new Date(), + ...values, + }), + ) + .then(() => + dispatch( + actions.updateCollection({ + id: project.id, + rev: project.rev, + status: 'submitted', + }), + ), + ) + .then(() => { + history.push('/') + }) + .catch(error => { + if (error.validationErrors) { + throw new SubmissionError() + } + }) // TODO: this is only here because prosemirror would save the title in the // metadata as html instead of plain text. we need to maybe find a better // position than here to perform this operation -const stripHtml = (htmlString) => { +const stripHtml = htmlString => { const temp = document.createElement('span') temp.innerHTML = htmlString return temp.textContent @@ -44,12 +50,14 @@ const stripHtml = (htmlString) => { const onChange = (values, dispatch, { project, version }) => { values.metadata.title = stripHtml(values.metadata.title) // see TODO above - return dispatch(actions.updateFragment(project, { - id: version.id, - rev: version.rev, - // submitted: false, - ...values - })) + return dispatch( + actions.updateFragment(project, { + id: version.id, + rev: version.rev, + // submitted: false, + ...values, + }), + ) // TODO: display a notification when saving/saving completes/saving fails } @@ -57,7 +65,10 @@ const onChange = (values, dispatch, { project, version }) => { export default compose( ConnectPage(({ match }) => [ actions.getCollection({ id: match.params.project }), - actions.getFragment({ id: match.params.project }, { id: match.params.version }) + actions.getFragment( + { id: match.params.project }, + { id: match.params.version }, + ), ]), connect( (state, { match }) => { @@ -67,31 +78,31 @@ export default compose( return { project, version } }, { - uploadFile - } + uploadFile, + }, ), withProps(({ version }) => { const paths = ['metadata', 'declarations', 'suggestions', 'notes', 'files'] return { - initialValues: pick(version, paths) + initialValues: pick(version, paths), } }), reduxForm({ - form: 'submit', // enableReinitialize: true, + form: 'submit', + onChange: debounce(onChange, 1000, { maxWait: 5000 }), onSubmit, - onChange: debounce(onChange, 1000, { maxWait: 5000 }) }), withState('confirming', 'setConfirming', false), withHandlers({ - toggleConfirming: ({valid, setConfirming, handleSubmit}) => () => { + toggleConfirming: ({ valid, setConfirming, handleSubmit }) => () => { if (valid) { setConfirming(confirming => !confirming) } else { // trigger dummy submit to mark all fields as touched handleSubmit(() => {})() } - } - }) + }, + }), )(Submit) diff --git a/packages/component-submit/src/components/Suggestions.js b/packages/component-submit/src/components/Suggestions.js index eab8683614b39588eb93daa134248963167ca982..ecba81ed8dee0f3a01f6830fadd68487eecdf152 100644 --- a/packages/component-submit/src/components/Suggestions.js +++ b/packages/component-submit/src/components/Suggestions.js @@ -7,80 +7,76 @@ import classes from './Suggestions.local.scss' const joinComma = join(',') const splitComma = split(',') -const SuggestedReviewerInput = input => - <TextField - placeholder="Add reviewer names" - {...input}/> - -const OpposedReviewerInput = input => - <TextField - placeholder="Add reviewer names" - {...input}/> - -const SuggestedEditorInput = input => - <TextField - placeholder="Add editor names" - {...input}/> - -const OpposedEditorInput = input => - <TextField - placeholder="Add editor names" - {...input}/> +const SuggestedReviewerInput = input => ( + <TextField placeholder="Add reviewer names" {...input} /> +) + +const OpposedReviewerInput = input => ( + <TextField placeholder="Add reviewer names" {...input} /> +) + +const SuggestedEditorInput = input => ( + <TextField placeholder="Add editor names" {...input} /> +) + +const OpposedEditorInput = input => ( + <TextField placeholder="Add editor names" {...input} /> +) const Suggestions = () => ( <FormSection name="suggestions"> <div className={classes.section} id="suggestions.reviewers"> <FormSection name="reviewers"> - <div className={classes.legend}> - Suggested or opposed reviewers - </div> + <div className={classes.legend}>Suggested or opposed reviewers</div> <div> <div className={classes.sublegend}>Suggested reviewers</div> <ValidatedField - name="suggested" + component={SuggestedReviewerInput} format={joinComma} + name="suggested" parse={splitComma} - component={SuggestedReviewerInput}/> + /> </div> <div> <div className={classes.sublegend}>Opposed reviewers</div> <ValidatedField - name="opposed" + component={OpposedReviewerInput} format={joinComma} + name="opposed" parse={splitComma} - component={OpposedReviewerInput}/> + /> </div> </FormSection> </div> <div className={classes.section} id="suggestions.editors"> <FormSection name="editors"> - <div className={classes.legend}> - Suggested or opposed editors - </div> + <div className={classes.legend}>Suggested or opposed editors</div> <div> <div className={classes.sublegend}>Suggested editors</div> <ValidatedField - name="suggested" + component={SuggestedEditorInput} format={joinComma} + name="suggested" parse={splitComma} - component={SuggestedEditorInput}/> + /> </div> <div> <div className={classes.sublegend}>Opposed editors</div> <ValidatedField - name="opposed" + component={OpposedEditorInput} format={joinComma} + name="opposed" parse={splitComma} - component={OpposedEditorInput}/> + /> </div> </FormSection> </div> diff --git a/packages/component-submit/src/components/Suggestions.local.scss b/packages/component-submit/src/components/Suggestions.local.scss index ce824553307d2346d6eeda7fc4925dfcc0d5ec74..d02d2cd879ce22ce2ee40ae8396a6ebab5f72b58 100644 --- a/packages/component-submit/src/components/Suggestions.local.scss +++ b/packages/component-submit/src/components/Suggestions.local.scss @@ -3,8 +3,8 @@ } .legend { - font-weight: 600; font-size: 1.1em; + font-weight: 600; margin-top: 3em; } diff --git a/packages/component-submit/src/components/SupplementaryFiles.js b/packages/component-submit/src/components/SupplementaryFiles.js index 9db16bb4e25031ff2dea54ad6eacea69a05ca22e..1fd8827a01d4a7b9c42b820fc6477374b6e5d6b9 100644 --- a/packages/component-submit/src/components/SupplementaryFiles.js +++ b/packages/component-submit/src/components/SupplementaryFiles.js @@ -3,22 +3,18 @@ import { FormSection } from 'redux-form' import { Supplementary, ValidatedField } from 'xpub-ui' import classes from './Metadata.local.scss' -const FileInput = uploadFile => input => - <Supplementary - uploadFile={uploadFile} - {...input}/> +const FileInput = uploadFile => input => ( + <Supplementary uploadFile={uploadFile} {...input} /> +) const SupplementaryFiles = ({ uploadFile }) => ( <FormSection name="files"> <div className={classes.section} id="files.supplementary"> - <div - className={classes.label} - htmlFor="supplementary">Upload supplementary materials + <div className={classes.label} htmlFor="supplementary"> + Upload supplementary materials </div> - <ValidatedField - name="supplementary" - component={FileInput(uploadFile)}/> + <ValidatedField component={FileInput(uploadFile)} name="supplementary" /> </div> </FormSection> ) diff --git a/packages/component-submit/src/components/Validot.js b/packages/component-submit/src/components/Validot.js index 4ffd9184a0fa23301a47bdf0da2f5da6216dcf47..25a73a3db52c4372867473cd962def12ce2cff25 100644 --- a/packages/component-submit/src/components/Validot.js +++ b/packages/component-submit/src/components/Validot.js @@ -14,7 +14,8 @@ const Validot = ({ input, meta, message }) => ( [classes.warning]: meta.warning, })} // message={message} - onClick={() => scrollIntoView(input.name)}/> + onClick={() => scrollIntoView(input.name)} + /> ) export default Validot diff --git a/packages/component-submit/src/components/Validot.local.scss b/packages/component-submit/src/components/Validot.local.scss index 6ee9c5a16dac7314c5b8505985e1681c06193e66..ee2548899c432ff323dffe6c37041fbb2e3bc8eb 100644 --- a/packages/component-submit/src/components/Validot.local.scss +++ b/packages/component-submit/src/components/Validot.local.scss @@ -3,39 +3,39 @@ } .root { + background: var(--color-circle); + border: 3px solid white; + border-radius: 100%; + cursor: pointer; display: block; - position: relative; - width: 25px; height: 25px; margin: 5px 10px; - cursor: pointer; - border: 3px solid white; - border-radius: 100%; - background: var(--color-circle); + position: relative; + width: 25px; } .root:hover { &::before { + background: var(--color-circle); + border-radius: 50%; content: " "; - width: 25px; height: 25px; + position: absolute; transform: scale(1.5); transform-origin: 50%; - position: absolute; - background: var(--color-circle); + width: 25px; z-index: -1; - border-radius: 50%; } &::after { - display: block; - width: 20ch; + color: var(--color-circle); content: "it would be nice to get a variable here for the message"; + display: block; font-size: 0.8em; + font-style: italic; margin-left: 3em; margin-top: -0.5em; - color: var(--color-circle); - font-style: italic; + width: 20ch; } } diff --git a/packages/component-submit/src/components/Validots.js b/packages/component-submit/src/components/Validots.js index e5961d29c5380426f6dc47c11e9fb861a16b109a..1b8307e35297db6af05e1ca88294ab9604b62a80 100644 --- a/packages/component-submit/src/components/Validots.js +++ b/packages/component-submit/src/components/Validots.js @@ -1,33 +1,29 @@ +import { map } from 'lodash' import React from 'react' import { Field } from 'redux-form' -import { map } from 'lodash' -import Validot from './Validot' import { connect } from 'react-redux' +import Validot from './Validot' + // TODO: is the order of map(form.registeredFields) guaranteed to be the same? // TODO: use journal config instead of form.registeredFields once using it to build the form // TODO: the Field rendered here overrides the validation in the other Field with the same name export const Validots = ({ form, valid, handleSubmit }) => ( <div> - {form.registeredFields && ( + {form.registeredFields && map(form.registeredFields, field => ( <div key={field.name}> - <Field - name={field.name} - component={Validot}/> + <Field component={Validot} name={field.name} /> </div> - )) - )} + ))} - <button - onClick={handleSubmit} - disabled={!valid}>Submit</button> + <button disabled={!valid} onClick={handleSubmit}> + Submit + </button> </div> ) -export default connect( - state => ({ - form: state.form.submit - }) -)(Validots) +export default connect(state => ({ + form: state.form.submit, +}))(Validots) diff --git a/packages/component-submit/src/index.js b/packages/component-submit/src/index.js index 0225ff41f4787662ca6fbc4ecc49c3894f11810c..6f1f42a64b1ecf4a71345e76fa416d89015cb96c 100644 --- a/packages/component-submit/src/index.js +++ b/packages/component-submit/src/index.js @@ -1,7 +1,5 @@ module.exports = { frontend: { - components: [ - () => require('./components') - ] - } + components: [() => require('./components')], + }, } diff --git a/packages/component-submit/styleguide.config.js b/packages/component-submit/styleguide.config.js index ef2282aa00478d48a99061dd2308cd04121e5f23..b119cf91b4bed8561aa4f45f2873b3454170bf54 100644 --- a/packages/component-submit/styleguide.config.js +++ b/packages/component-submit/styleguide.config.js @@ -1,20 +1,22 @@ module.exports = { title: 'xpub submit style guide', styleguideComponents: { - StyleGuideRenderer: require.resolve('xpub-styleguide/src/components/StyleGuideRenderer'), - Wrapper: require.resolve('xpub-styleguide/src/components/Wrapper') + StyleGuideRenderer: require.resolve( + 'xpub-styleguide/src/components/StyleGuideRenderer', + ), + Wrapper: require.resolve('xpub-styleguide/src/components/Wrapper'), }, context: { - faker: 'faker' + faker: 'faker', }, skipComponentsWithoutExample: true, serverPort: 6064, theme: { fontFamily: { - base: '"Fira Sans", sans-serif' + base: '"Fira Sans", sans-serif', }, color: { - link: 'cornflowerblue' - } - } + link: 'cornflowerblue', + }, + }, } diff --git a/packages/xpub-collabra/app/app.js b/packages/xpub-collabra/app/app.js index f71e517b90a5a15dcf0e61c29ad8f2dff0a1053b..a66d52c4d600fda898fc31ebcb401081a1edf639 100644 --- a/packages/xpub-collabra/app/app.js +++ b/packages/xpub-collabra/app/app.js @@ -3,12 +3,14 @@ import ReactDOM from 'react-dom' import { AppContainer } from 'react-hot-loader' import { Provider as StoreProvider } from 'react-redux' import { Router } from 'react-router-dom' -import { configureStore } from 'pubsweet-client' import createHistory from 'history/createBrowserHistory' + +import { configureStore } from 'pubsweet-client' import { JournalProvider } from 'xpub-journal' +import 'xpub-theme' + import * as journal from './config/journal' import Root from './routes' -import 'xpub-theme' const history = createHistory() const store = configureStore(history, {}) @@ -19,12 +21,12 @@ const render = () => { <StoreProvider store={store}> <JournalProvider journal={journal}> <Router history={history}> - <Root/> + <Root /> </Router> </JournalProvider> </StoreProvider> </AppContainer>, - document.getElementById('root') + document.getElementById('root'), ) } diff --git a/packages/xpub-collabra/app/config/journal/article-sections.js b/packages/xpub-collabra/app/config/journal/article-sections.js index 3f797b098741359ce4f54e473919585a2f64189a..ab5c5e94d62fc58cf8bb7b12a7ac462f1ddba050 100644 --- a/packages/xpub-collabra/app/config/journal/article-sections.js +++ b/packages/xpub-collabra/app/config/journal/article-sections.js @@ -1,30 +1,30 @@ export default [ { + label: 'Cognitive Psychology', value: 'cognitive-psychology', - label: 'Cognitive Psychology' }, { + label: 'Social Psychology', value: 'social-psychology', - label: 'Social Psychology' }, { + label: 'Personality Psychology', value: 'personality-psychology', - label: 'Personality Psychology' }, { + label: 'Developmental Psychology', value: 'developmental-psychology', - label: 'Developmental Psychology' }, { + label: 'Clinical Psychology', value: 'clinical-psychology', - label: 'Clinical Psychology' }, { + label: 'Organizational Behavior', value: 'organizational-behavior', - label: 'Organizational Behavior' }, { + label: 'Methodology and Research Practice', value: 'methodology', - label: 'Methodology and Research Practice' }, ] diff --git a/packages/xpub-collabra/app/config/journal/article-types.js b/packages/xpub-collabra/app/config/journal/article-types.js index 9a456260fc2644fa543b90bed5bb351af41f14bb..a5d08e5f9823fcce6aa1ff85435a1b798ac5629a 100644 --- a/packages/xpub-collabra/app/config/journal/article-types.js +++ b/packages/xpub-collabra/app/config/journal/article-types.js @@ -1,18 +1,18 @@ export default [ { + label: 'Original Research Report', value: 'original-research', - label: 'Original Research Report' }, { + label: 'Review', value: 'review', - label: 'Review' }, { + label: 'Opinion/Commentary', value: 'opinion', - label: 'Opinion/Commentary' }, { + label: 'Registered Report', value: 'registered-report', - label: 'Registered Report' }, ] diff --git a/packages/xpub-collabra/app/config/journal/decisions.js b/packages/xpub-collabra/app/config/journal/decisions.js index 7b9e6dabf698f0ab0c07537a724679d6d8db7b41..95be4c5d8a550af1cc3de9de32a1da3d5862d98d 100644 --- a/packages/xpub-collabra/app/config/journal/decisions.js +++ b/packages/xpub-collabra/app/config/journal/decisions.js @@ -1,22 +1,23 @@ export default { accept: { - label: 'Accept', color: 'green', - message: 'The submission has been accepted for publication' - }, - minor: { - label: 'Minor revisions', - color: 'orange', - message: 'The submission will be accepted for publication after minor changes' + label: 'Accept', + message: 'The submission has been accepted for publication', }, major: { - label: 'Major revisions', color: 'yellow', - message: 'The requested changes must be made before submission for review' + label: 'Major revisions', + message: 'The requested changes must be made before submission for review', + }, + minor: { + color: 'orange', + label: 'Minor revisions', + message: + 'The submission will be accepted for publication after minor changes', }, reject: { - label: 'Reject', color: 'red', - message: 'The submission is not acceptable for publication' + label: 'Reject', + message: 'The submission is not acceptable for publication', }, } diff --git a/packages/xpub-collabra/app/config/journal/declarations.js b/packages/xpub-collabra/app/config/journal/declarations.js index 803db14edec42d89c903fbade1f6c6943def29fc..012e4d46c2bfe3b20da969a9277a391d61c18094 100644 --- a/packages/xpub-collabra/app/config/journal/declarations.js +++ b/packages/xpub-collabra/app/config/journal/declarations.js @@ -2,27 +2,27 @@ export default { questions: [ { id: 'openData', - legend: 'Data is open' + legend: 'Data is open', }, { id: 'previouslySubmitted', - legend: 'Previously submitted' + legend: 'Previously submitted', }, { id: 'openPeerReview', - legend: 'Open peer review' + legend: 'Open peer review', }, { id: 'streamlinedReview', - legend: 'Streamlined review' + legend: 'Streamlined review', }, { id: 'researchNexus', - legend: 'Submitted as part of the research nexus?' + legend: 'Submitted as part of the research nexus?', }, { id: 'preregistered', - legend: 'Pre-registered?' - } - ] + legend: 'Pre-registered?', + }, + ], } diff --git a/packages/xpub-collabra/app/config/journal/editors.js b/packages/xpub-collabra/app/config/journal/editors.js index a3af69f0bba715db1f757b70efa0a37b6e755519..9c2affbc43fbe73e0b011e8d2a715d27581f35c1 100644 --- a/packages/xpub-collabra/app/config/journal/editors.js +++ b/packages/xpub-collabra/app/config/journal/editors.js @@ -1,32 +1,32 @@ export default { + handlingEditor: [ + { + name: 'Handling Editor One', + user: 5, + }, + { + name: 'Handling Editor Two', + user: 6, + }, + ], managingEditor: [ { + name: 'Managing Editor One', user: 1, - name: "Managing Editor One" }, { + name: 'Managing Editor Two', user: 2, - name: "Managing Editor Two" - } + }, ], seniorEditor: [ { + name: 'Senior Editor One', user: 3, - name: "Senior Editor One" }, { + name: 'Senior Editor Two', user: 4, - name: "Senior Editor Two" - } - ], - handlingEditor: [ - { - user: 5, - name: "Handling Editor One" }, - { - user: 6, - name: "Handling Editor Two" - } - ] + ], } diff --git a/packages/xpub-collabra/app/config/journal/metadata.js b/packages/xpub-collabra/app/config/journal/metadata.js index 0040ca7d9ea157573236e19b06a4c4d9eb8ad740..eee1ed1efe89afc3b158e9ef29247f46202bf82c 100644 --- a/packages/xpub-collabra/app/config/journal/metadata.js +++ b/packages/xpub-collabra/app/config/journal/metadata.js @@ -1,4 +1,4 @@ export default { + issn: '2474-7394', name: 'Collabra: Psychology', - issn: '2474-7394' } diff --git a/packages/xpub-collabra/app/config/journal/recommendations.js b/packages/xpub-collabra/app/config/journal/recommendations.js index e62b4f88c51cc6dfaf15d74bb21edf0e4281e93e..f65e0d670ba866846f46282045eb2225dde91878 100644 --- a/packages/xpub-collabra/app/config/journal/recommendations.js +++ b/packages/xpub-collabra/app/config/journal/recommendations.js @@ -1,17 +1,17 @@ export default [ { - value: 'accept', + color: 'green', label: 'Accept', - color: 'green' + value: 'accept', }, { - value: 'revise', + color: 'orange', label: 'Revise', - color: 'orange' + value: 'revise', }, { - value: 'reject', + color: 'red', label: 'Reject', - color: 'red' - } + value: 'reject', + }, ] diff --git a/packages/xpub-collabra/app/config/journal/roles.js b/packages/xpub-collabra/app/config/journal/roles.js index 17420307448c51618a351691035b55a7b6007a92..0f9334d4c66a69a75359e50150a8f7b40f153ee6 100644 --- a/packages/xpub-collabra/app/config/journal/roles.js +++ b/packages/xpub-collabra/app/config/journal/roles.js @@ -1,6 +1,6 @@ export default { author: 'Author', - seniorEditor: 'Senior Editor', - managingEditor: 'Managing Editor', handlingEditor: 'Handling Editor', + managingEditor: 'Managing Editor', + seniorEditor: 'Senior Editor', } diff --git a/packages/xpub-collabra/app/config/journal/sections.js b/packages/xpub-collabra/app/config/journal/sections.js index 419171898b0abb22f9c5917684de31809de75cb2..72bbd760b76499147343cb51e9a73954f71eade3 100644 --- a/packages/xpub-collabra/app/config/journal/sections.js +++ b/packages/xpub-collabra/app/config/journal/sections.js @@ -1,6 +1,6 @@ export default [ { id: 'submissions', - label: 'My Submissions' - } + label: 'My Submissions', + }, ] diff --git a/packages/xpub-collabra/app/routes.js b/packages/xpub-collabra/app/routes.js index b66c227d2bf92b9923c312d072643ce85365b26a..88a0a092fe5d4c0636c872a1b82dea0365114429 100644 --- a/packages/xpub-collabra/app/routes.js +++ b/packages/xpub-collabra/app/routes.js @@ -2,50 +2,76 @@ import React from 'react' import { Route, withRouter } from 'react-router-dom' import loadable from 'loadable-components' -import { App } from 'pubsweet-component-xpub-app/src/components' +import App from 'pubsweet-component-xpub-app/src/components' import { PrivateRoute, SignupPage, LoginPage, - LogoutPage + LogoutPage, } from 'pubsweet-component-xpub-authentication/src/components' const DashboardPage = loadable(() => - import('pubsweet-component-xpub-dashboard/src/components/DashboardPage')) + import('pubsweet-component-xpub-dashboard/src/components/DashboardPage'), +) const SubmitPage = loadable(() => - import('pubsweet-component-xpub-submit/src/components/SubmitPage')) + import('pubsweet-component-xpub-submit/src/components/SubmitPage'), +) const ManuscriptPage = loadable(() => - import('pubsweet-component-xpub-manuscript/src/components/ManuscriptPage')) + import('pubsweet-component-xpub-manuscript/src/components/ManuscriptPage'), +) const ReviewersPage = loadable(() => - import('pubsweet-component-xpub-review/src/components/ReviewersPage')) + import('pubsweet-component-xpub-review/src/components/ReviewersPage'), +) const ReviewPage = loadable(() => - import('pubsweet-component-xpub-review/src/components/ReviewPage')) + import('pubsweet-component-xpub-review/src/components/ReviewPage'), +) const DecisionPage = loadable(() => - import('pubsweet-component-xpub-review/src/components/DecisionPage')) + import('pubsweet-component-xpub-review/src/components/DecisionPage'), +) // TODO: use componentDidMount to fetch the current user before rendering? const Root = () => ( <App> - <PrivateRoute exact path="/" component={DashboardPage}/> - <PrivateRoute exact path="/projects/:project/versions/:version/submit" component={SubmitPage}/> - <PrivateRoute exact path="/projects/:project/versions/:version/manuscript" component={ManuscriptPage}/> - <PrivateRoute exact path="/projects/:project/versions/:version/reviewers" component={ReviewersPage}/> - <PrivateRoute exact path="/projects/:project/versions/:version/reviews/:review" component={ReviewPage}/> - <PrivateRoute exact path="/projects/:project/versions/:version/decisions/:decision" component={DecisionPage}/> + <PrivateRoute component={DashboardPage} exact path="/" /> + <PrivateRoute + component={SubmitPage} + exact + path="/projects/:project/versions/:version/submit" + /> + <PrivateRoute + component={ManuscriptPage} + exact + path="/projects/:project/versions/:version/manuscript" + /> + <PrivateRoute + component={ReviewersPage} + exact + path="/projects/:project/versions/:version/reviewers" + /> + <PrivateRoute + component={ReviewPage} + exact + path="/projects/:project/versions/:version/reviews/:review" + /> + <PrivateRoute + component={DecisionPage} + exact + path="/projects/:project/versions/:version/decisions/:decision" + /> - <PrivateRoute exact path="/logout" component={LogoutPage}/> + <PrivateRoute component={LogoutPage} exact path="/logout" /> - <Route exact path="/signup" component={SignupPage}/> - <Route exact path="/login" component={LoginPage}/> + <Route component={SignupPage} exact path="/signup" /> + <Route component={LoginPage} exact path="/login" /> - {/*<Redirect from="/" to="/dashboard"/>*/} + {/* <Redirect from="/" to="/dashboard"/> */} </App> ) diff --git a/packages/xpub-collabra/config/authsome.js b/packages/xpub-collabra/config/authsome.js index 316dac27440d44e314c06c2b8c3c3b7829f6109e..17447be2eaa63ecd8dc407122b67625b8676f1a1 100644 --- a/packages/xpub-collabra/config/authsome.js +++ b/packages/xpub-collabra/config/authsome.js @@ -1,4 +1,3 @@ -module.exports = (user, operation, project, version) => { +module.exports = (user, operation, project, version) => // console.log({ user, operation, project, version }) - return true // TODO -} + true // TODO diff --git a/packages/xpub-collabra/config/default.js b/packages/xpub-collabra/config/default.js index 749f2f6f4cb634d2f7ec1aa5584d637c75962b3f..095442582cfe20cdf45e5ffe9c2c7f794317127c 100644 --- a/packages/xpub-collabra/config/default.js +++ b/packages/xpub-collabra/config/default.js @@ -8,33 +8,38 @@ module.exports = { mode: path.resolve(__dirname, 'authsome.js'), teams: { // TODO - } + }, }, validations: path.resolve(__dirname, 'validations.js'), pubsweet: { - components + components, }, 'pubsweet-server': { - dbPath: process.env.PUBSWEET_DB || path.join(__dirname, '..', 'api', 'db', environment), + dbPath: + process.env.PUBSWEET_DB || + path.join(__dirname, '..', 'api', 'db', environment), }, 'pubsweet-client': { API_ENDPOINT: 'http://localhost:3000/api', 'login-redirect': '/', 'redux-log': false, - theme: process.env.PUBSWEET_THEME + theme: process.env.PUBSWEET_THEME, }, 'mail-transport': { - sendmail: true + sendmail: true, }, 'password-reset': { - url: process.env.PUBSWEET_PASSWORD_RESET_URL || 'http://localhost:3000/password-reset', - sender: process.env.PUBSWEET_PASSWORD_RESET_SENDER || 'dev@example.com' + url: + process.env.PUBSWEET_PASSWORD_RESET_URL || + 'http://localhost:3000/password-reset', + sender: process.env.PUBSWEET_PASSWORD_RESET_SENDER || 'dev@example.com', }, 'pubsweet-component-ink-backend': { - inkEndpoint: process.env.INK_ENDPOINT || 'http://inkdemo-api.coko.foundation', + inkEndpoint: + process.env.INK_ENDPOINT || 'http://inkdemo-api.coko.foundation', email: process.env.INK_USERNAME, password: process.env.INK_PASSWORD, - maxRetries: 500 + maxRetries: 500, }, publicKeys: ['pubsweet-client', 'authsome', 'validations'], } diff --git a/packages/xpub-collabra/config/validations.js b/packages/xpub-collabra/config/validations.js index 4f134375b918d92684356d72239a2710ac2f3514..db61056394a3e2536b38e5dad8a74d88099348cb 100644 --- a/packages/xpub-collabra/config/validations.js +++ b/packages/xpub-collabra/config/validations.js @@ -1,7 +1,8 @@ const Joi = require('joi') module.exports = { - collection: { // project + collection: { + // project collectionType: Joi.string(), created: Joi.date(), title: Joi.string(), @@ -27,11 +28,11 @@ module.exports = { suggestions: Joi.object({ reviewers: Joi.object({ suggested: Joi.array().items(Joi.string()), - opposed: Joi.array().items(Joi.string()) + opposed: Joi.array().items(Joi.string()), }), editors: Joi.object({ suggested: Joi.array().items(Joi.string()), - opposed: Joi.array().items(Joi.string()) + opposed: Joi.array().items(Joi.string()), }), }), files: Joi.object({ @@ -39,29 +40,31 @@ module.exports = { name: Joi.string().required(), type: Joi.string(), size: Joi.number(), - url: Joi.string() + url: Joi.string(), }), - supplementary: Joi.array().items(Joi.object({ - name: Joi.string().required(), - type: Joi.string(), - size: Joi.number(), - url: Joi.string() - })) + supplementary: Joi.array().items( + Joi.object({ + name: Joi.string().required(), + type: Joi.string(), + size: Joi.number(), + url: Joi.string(), + }), + ), }), notes: Joi.object({ fundingAcknowledgement: Joi.string(), - specialInstructions: Joi.string() + specialInstructions: Joi.string(), }), reviewers: Joi.array(), lock: Joi.object(), decision: Joi.object(), - } + }, ], user: { name: Joi.string(), // TODO: add "name" to the login form - roles: Joi.object() + roles: Joi.object(), }, team: { - group: Joi.string() - } + group: Joi.string(), + }, } diff --git a/packages/xpub-collabra/webpack/common-resolve.js b/packages/xpub-collabra/webpack/common-resolve.js index 0ba87dc649b3e38bbab90b77b7ba31be398c030a..4f12a5c49057d1a2ea49e8647237ac37abb1cbdc 100644 --- a/packages/xpub-collabra/webpack/common-resolve.js +++ b/packages/xpub-collabra/webpack/common-resolve.js @@ -1,14 +1,14 @@ const path = require('path') const config = require('config') const fs = require('fs-extra') -const {pick} = require('lodash') +const { pick } = require('lodash') // can't use node-config in webpack so save whitelisted client config into the build and alias it below const outputPath = path.resolve(__dirname, '..', '_build', 'assets') const clientConfig = pick(config, config.publicKeys) fs.ensureDirSync(outputPath) const clientConfigPath = path.join(outputPath, 'client-config.json') -fs.writeJsonSync(clientConfigPath, clientConfig, {spaces: 2}) +fs.writeJsonSync(clientConfigPath, clientConfig, { spaces: 2 }) module.exports = { // symlinks: false, // needed so that babel doesn't look for plugins in components @@ -16,11 +16,11 @@ module.exports = { path.resolve(__dirname, '..'), // needed for resolving app/routes path.resolve(__dirname, '../node_modules'), path.resolve(__dirname, '../../../node_modules'), - 'node_modules' + 'node_modules', ], alias: { joi: 'joi-browser', - config: clientConfigPath + config: clientConfigPath, }, extensions: ['.js', '.jsx'], } diff --git a/packages/xpub-collabra/webpack/common-rules.js b/packages/xpub-collabra/webpack/common-rules.js index 9597088c4240af8297c8026369c66f8026994412..6abb4982adb068370ee63cc82260d764fd1fa83d 100644 --- a/packages/xpub-collabra/webpack/common-rules.js +++ b/packages/xpub-collabra/webpack/common-rules.js @@ -8,7 +8,7 @@ const requireComponentsString = components // "client" or "frontend" for backwards compatibility return component.client || component.frontend }) - .map(name => "require('" + name + "')") + .map(name => `require('${name}')`) .join(', ') // paths that use ES6 scripts and CSS modules @@ -31,8 +31,8 @@ module.exports = [ loader: 'string-replace-loader', options: { search: 'PUBSWEET_COMPONENTS', - replace: '[' + requireComponentsString + ']' - } + replace: `[${requireComponentsString}]`, + }, }, // loaders @@ -47,12 +47,10 @@ module.exports = [ presets: [ [require('babel-preset-env'), { modules: false }], require('babel-preset-react'), - require('babel-preset-stage-2') + require('babel-preset-stage-2'), ], - plugins: [ - require('react-hot-loader/babel'), - ] - } + plugins: [require('react-hot-loader/babel')], + }, }, // CSS Modules @@ -66,9 +64,9 @@ module.exports = [ options: { modules: true, localIdentName: '[name]_[local]-[hash:base64:8]', - } - } - ] + }, + }, + ], }, // SCSS Modules @@ -83,19 +81,16 @@ module.exports = [ modules: true, importLoaders: 1, localIdentName: '[name]_[local]-[hash:base64:8]', - } + }, }, - 'sass-loader' - ] + 'sass-loader', + ], }, // global CSS { test: /\.css$/, - use: [ - 'style-loader', - 'css-loader', - ] + use: ['style-loader', 'css-loader'], }, // global SCSS @@ -104,14 +99,14 @@ module.exports = [ use: [ 'style-loader', 'css-loader', // TODO: importLoaders: 1? - 'sass-loader' - ] + 'sass-loader', + ], }, // HTML (needed?) { test: /\.html$/, - use: 'html-loader' + use: 'html-loader', }, // files @@ -120,8 +115,8 @@ module.exports = [ loader: 'file-loader', options: { name: 'static/media/[name].[hash:8].[ext]', - } - } - ] + }, + }, + ], }, ] diff --git a/packages/xpub-collabra/webpack/webpack.development.config.js b/packages/xpub-collabra/webpack/webpack.development.config.js index 15e4104d6bbcb7ef484901087b35313dbac9568e..dbe5ee2c990c0bee752f3d5fc5763ad74fe21032 100644 --- a/packages/xpub-collabra/webpack/webpack.development.config.js +++ b/packages/xpub-collabra/webpack/webpack.development.config.js @@ -18,17 +18,17 @@ module.exports = [ app: [ 'react-hot-loader/patch', 'webpack-hot-middleware/client?reload=true', - './app' - ] + './app', + ], }, output: { path: path.join(__dirname, '..', '_build', 'assets'), filename: '[name].js', - publicPath: '/assets/' + publicPath: '/assets/', }, devtool: 'eval', // 'cheap-module-source-map', module: { - rules + rules, }, resolve, plugins: [ @@ -40,15 +40,13 @@ module.exports = [ }), new webpack.ContextReplacementPlugin(/./, __dirname, { [config.authsome.mode]: config.authsome.mode, - [config.validations]: config.validations + [config.validations]: config.validations, }), - new CopyWebpackPlugin([ - { from: '../static' } - ]) + new CopyWebpackPlugin([{ from: '../static' }]), ], node: { fs: 'empty', - __dirname: true - } - } + __dirname: true, + }, + }, ] diff --git a/packages/xpub-collabra/webpack/webpack.production.config.js b/packages/xpub-collabra/webpack/webpack.production.config.js index 4496db410566aa1679a4dd37f1f65689c23d1bb9..aa38c5e70e9b2db9eda6fb55344518a0570f6e84 100644 --- a/packages/xpub-collabra/webpack/webpack.production.config.js +++ b/packages/xpub-collabra/webpack/webpack.production.config.js @@ -17,40 +17,38 @@ module.exports = [ target: 'web', context: path.join(__dirname, '..', 'app'), entry: { - app: ['./app'] + app: ['./app'], }, output: { path: path.join(__dirname, '..', '_build', 'assets'), filename: '[name].[hash].js', - publicPath: '/assets/' + publicPath: '/assets/', }, module: { - rules + rules, }, resolve, plugins: [ new HtmlWebpackPlugin({ title: 'xpub', template: '../app/index.ejs', // Load a custom template - inject: 'body' // Inject all scripts into the body + inject: 'body', // Inject all scripts into the body }), new webpack.DefinePlugin({ - 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV) + 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), }), new webpack.ContextReplacementPlugin(/./, __dirname, { [config.authsome.mode]: config.authsome.mode, - [config.validations]: config.validations + [config.validations]: config.validations, }), new ExtractTextPlugin('styles/main.css'), - new CopyWebpackPlugin([ - { from: '../static' } - ]), + new CopyWebpackPlugin([{ from: '../static' }]), new webpack.optimize.AggressiveMergingPlugin(), new webpack.optimize.OccurrenceOrderPlugin(), ], node: { fs: 'empty', - __dirname: true - } - } + __dirname: true, + }, + }, ] diff --git a/packages/xpub-collabra/webpack/webpack.test.config.js b/packages/xpub-collabra/webpack/webpack.test.config.js index 5cc4b70b37100e3f642ae76d209e51aa1ee9c19e..3a473a1f2620b94ae33491f381cf952f9e218e9d 100644 --- a/packages/xpub-collabra/webpack/webpack.test.config.js +++ b/packages/xpub-collabra/webpack/webpack.test.config.js @@ -15,19 +15,15 @@ module.exports = [ target: 'web', context: path.join(__dirname, '..', 'app'), entry: { - app: [ - 'react-hot-loader/patch', - 'webpack-hot-middleware/client', - './app' - ] + app: ['react-hot-loader/patch', 'webpack-hot-middleware/client', './app'], }, output: { path: path.join(__dirname, '..', '_build', 'assets'), filename: '[name].js', - publicPath: '/assets/' + publicPath: '/assets/', }, module: { - rules + rules, }, resolve, plugins: [ @@ -38,17 +34,15 @@ module.exports = [ }), new webpack.ContextReplacementPlugin(/./, __dirname, { [config.authsome.mode]: config.authsome.mode, - [config.validations]: config.validations + [config.validations]: config.validations, }), - new CopyWebpackPlugin([ - { from: '../static' } - ]), + new CopyWebpackPlugin([{ from: '../static' }]), new webpack.optimize.AggressiveMergingPlugin(), new webpack.optimize.OccurrenceOrderPlugin(), ], node: { fs: 'empty', - __dirname: true - } - } + __dirname: true, + }, + }, ] diff --git a/packages/xpub-connect/src/components/ConnectPage.js b/packages/xpub-connect/src/components/ConnectPage.js index 8d89bd3e21855233972b04057a44942d3f11dedf..8f5aa92910f6917879e95d1c9c6b0a7f059e61c6 100644 --- a/packages/xpub-connect/src/components/ConnectPage.js +++ b/packages/xpub-connect/src/components/ConnectPage.js @@ -7,20 +7,20 @@ import classes from './ConnectPage.local.scss' const ConnectPage = requirements => WrappedComponent => { class ConnectedComponent extends React.Component { state = { - fetching: false, complete: false, - error: null + error: null, + fetching: false, } - componentDidMount () { + componentDidMount = () => { this.fetch(this.props) } - componentWillReceiveProps (nextProps) { + componentWillReceiveProps = nextProps => { this.fetch(nextProps) } - fetch ({ isAuthenticated }) { + fetch({ isAuthenticated }) { if (!isAuthenticated) { return } @@ -31,49 +31,45 @@ const ConnectPage = requirements => WrappedComponent => { this.setState({ fetching: true, - complete: false + complete: false, }) const requests = requirements(this.props).map(this.props.dispatch) - Promise.all(requests).then(() => { - this.setState({ - fetching: false, - complete: true, + Promise.all(requests) + .then(() => { + this.setState({ + fetching: false, + complete: true, + }) }) - }).catch(error => { - console.error(error) + .catch(error => { + console.error(error) - this.setState({ - error: error.message - }) + this.setState({ + error: error.message, + }) - throw error // rethrow - }) + throw error // rethrow + }) } - render () { + render() { const { complete, error } = this.state - if (error) return ( - <div className={classes.error}>{error}</div> - ) + if (error) return <div className={classes.error}>{error}</div> - if (!complete) return ( - <div className={classes.bar}>loading…</div> - ) + if (!complete) return <div className={classes.bar}>loading…</div> - return <WrappedComponent {...this.props}/> + return <WrappedComponent {...this.props} /> } } return compose( withRouter, - connect( - state => ({ - isAuthenticated: state.currentUser.isAuthenticated - }) - ) + connect(state => ({ + isAuthenticated: state.currentUser.isAuthenticated, + })), )(ConnectedComponent) } diff --git a/packages/xpub-edit/src/components/Editor.js b/packages/xpub-edit/src/components/Editor.js index 26c0d4ab400d237be152da27b190939489814d02..40b2418adccad65bb06698cdf4842d45c37679b0 100644 --- a/packages/xpub-edit/src/components/Editor.js +++ b/packages/xpub-edit/src/components/Editor.js @@ -2,17 +2,18 @@ import React from 'react' import classnames from 'classnames' import { EditorState } from 'prosemirror-state' import { EditorView } from 'prosemirror-view' -import MenuBar from './MenuBar' import baseClasses from 'prosemirror-view/style/prosemirror.css' + +import MenuBar from './MenuBar' import classes from './Editor.local.css' import decorations from '../decorations' class Editor extends React.Component { - constructor (props) { + constructor(props) { super(props) this.state = { - state: EditorState.create(props.options) + state: EditorState.create(props.options), } } @@ -24,16 +25,18 @@ class Editor extends React.Component { dispatchTransaction: this.dispatchTransaction, decorations: decorations({ props: this.props, - classes + classes, }), attributes: { - class: classnames(baseClasses.ProseMirror, classes.ProseMirror) + class: classnames(baseClasses.ProseMirror, classes.ProseMirror), }, handleDOMEvents: { - blur: this.props.onBlur ? view => { - this.props.onBlur(view.state.doc.content) - } : null - } + blur: this.props.onBlur + ? view => { + this.props.onBlur(view.state.doc.content) + } + : null, + }, }) if (this.props.autoFocus) { @@ -48,7 +51,7 @@ class Editor extends React.Component { this.props.onChange(state.doc.content) } - render () { + render() { const { options: { menu }, title } = this.props const { state } = this.state @@ -56,16 +59,14 @@ class Editor extends React.Component { <div> {menu && ( <MenuBar + dispatch={this.dispatchTransaction} menu={menu} - title={title} state={state} - dispatch={this.dispatchTransaction} + title={title} /> )} - <div - ref={this.createEditorView} - /> + <div ref={this.createEditorView} /> </div> ) } diff --git a/packages/xpub-edit/src/components/Editor.local.css b/packages/xpub-edit/src/components/Editor.local.css index 19ded8ead9327e7b62156dd845b1932fd322556d..5068951f0afa8f3434b89f88ae765b288d439978 100644 --- a/packages/xpub-edit/src/components/Editor.local.css +++ b/packages/xpub-edit/src/components/Editor.local.css @@ -1,10 +1,10 @@ .ProseMirror { - font-family: var(--font-reviewer); - font-size: 0.8em; - line-height: 1.8; background: linear-gradient(to right, transparent 0%, transparent 2px, white 2px, white 4px), linear-gradient(white 0%, white 90%, var(--color-back) 92%, white 100%); background-repeat: repeat-X, repeat-Y; background-size: 4px 100%, 100% 1.8em; + font-family: var(--font-reviewer); + font-size: 0.8em; + line-height: 1.8; min-height: 1em; } @@ -27,16 +27,16 @@ } .ProseMirror hr { - padding: 2px 10px; border: none; margin: 1em 0; + padding: 2px 10px; } .ProseMirror hr::after { + background-color: silver; content: ""; display: block; height: 1px; - background-color: silver; line-height: 2px; } @@ -46,10 +46,10 @@ } .ProseMirror blockquote { - padding-left: 1em; border-left: 3px solid #eee; margin-left: 0; margin-right: 0; + padding-left: 1em; } .ProseMirror img { @@ -62,19 +62,19 @@ padding: 2px 5px; } -.ProseMirror:focus .placeholder { - display: none; -} - .ProseMirror .placeholder { - font-style: italic; - font-family: var(--font-interface); color: #aaa; - pointer-events: none; + font-family: var(--font-interface); + font-style: italic; height: 0; + pointer-events: none; +} + +.ProseMirror:focus .placeholder { + display: none; } .ProseMirror p { - margin-top: 0; margin-bottom: 0; + margin-top: 0; } diff --git a/packages/xpub-edit/src/components/HtmlEditor.js b/packages/xpub-edit/src/components/HtmlEditor.js index 9f6ff1456d5d854eb57265070f0712d088f9155a..48519fb4a81a3284a822099870619199936d27a0 100644 --- a/packages/xpub-edit/src/components/HtmlEditor.js +++ b/packages/xpub-edit/src/components/HtmlEditor.js @@ -25,7 +25,7 @@ const serializer = schema => { } class HtmlEditor extends React.Component { - componentWillMount () { + componentWillMount() { const { value, onChange, onBlur, options } = this.props const { schema } = options @@ -34,27 +34,37 @@ class HtmlEditor extends React.Component { options.doc = parse(value) - this.onChange = debounce(value => { - onChange(serialize(value)) - }, 1000, { maxWait: 5000 }) + this.onChange = debounce( + value => { + onChange(serialize(value)) + }, + 1000, + { maxWait: 5000 }, + ) this.onBlur = value => { onBlur(serialize(value)) } } - render () { - const { options, className, placeholder, placeholderClassName, title } = this.props + render() { + const { + options, + className, + placeholder, + placeholderClassName, + title, + } = this.props return ( <Editor - options={options} className={className} + onBlur={this.onBlur} + onChange={this.onChange} + options={options} placeholder={placeholder} placeholderClassName={placeholderClassName} title={title} - onChange={this.onChange} - onBlur={this.onBlur} /> ) } diff --git a/packages/xpub-edit/src/components/HtmlViewer.js b/packages/xpub-edit/src/components/HtmlViewer.js index 30d3f263a4aaf50583dd79510ba94cdcada45133..759d8cd912e10c3458b002d25f763d22bf9c01c9 100644 --- a/packages/xpub-edit/src/components/HtmlViewer.js +++ b/packages/xpub-edit/src/components/HtmlViewer.js @@ -14,7 +14,7 @@ const parser = schema => { } class HtmlViewer extends React.Component { - componentWillMount () { + componentWillMount() { const { value, options } = this.props const { schema } = options @@ -23,14 +23,10 @@ class HtmlViewer extends React.Component { options.doc = parse(value) } - render () { + render() { const { options } = this.props - return ( - <Viewer - options={options} - /> - ) + return <Viewer options={options} /> } } diff --git a/packages/xpub-edit/src/components/MenuBar.js b/packages/xpub-edit/src/components/MenuBar.js index 65c4c6f4613b9df141f15387e35b4944f530a53d..605c74af4dbc240dd852532a9deb0a939d9f3933 100644 --- a/packages/xpub-edit/src/components/MenuBar.js +++ b/packages/xpub-edit/src/components/MenuBar.js @@ -11,22 +11,22 @@ const MenuBar = ({ title, menu, state, dispatch }) => { const Button = (item, key) => ( <button - key={key} className={classnames({ [classes.button]: true, - [classes.active]: item.active && item.active(state) + [classes.active]: item.active && item.active(state), })} - title={item.title} disabled={item.enable && !item.enable(state)} + key={key} onMouseDown={handle(item.run)} - >{item.content}</button> + title={item.title} + > + {item.content} + </button> ) return ( <div className={classes.toolbar}> - {title && ( - <div className={classes.title}>{title}</div> - )} + {title && <div className={classes.title}>{title}</div>} {menu.marks && map(menu.marks, Button)} {menu.blocks && map(menu.blocks, Button)} diff --git a/packages/xpub-edit/src/components/MenuBar.local.css b/packages/xpub-edit/src/components/MenuBar.local.css index 83367cfc852db88eab43423a134288fa34a3c826..7f5aab4999a0b290c2582a543512dc729c0e4305 100644 --- a/packages/xpub-edit/src/components/MenuBar.local.css +++ b/packages/xpub-edit/src/components/MenuBar.local.css @@ -1,25 +1,25 @@ .toolbar { + align-items: baseline; display: flex; margin-bottom: 0.8em; - align-items: baseline; margin-top: 0; } .button { - border: none; background: white; - cursor: pointer; + border: none; + border-bottom: 2px solid transparent; color: #777; - padding: 0; + cursor: pointer; + height: 20px; margin: 0 0.4em; - border-bottom: 2px solid transparent; min-width: 20px; - height: 20px; + padding: 0; } .button:hover { - color: var(--color-primary); border-bottom: 2px solid var(--color-primary); + color: var(--color-primary); } .button.active { diff --git a/packages/xpub-edit/src/components/Viewer.js b/packages/xpub-edit/src/components/Viewer.js index a638c5b5093d6d9e0af9df51a532b5668943f1d7..c61a6591cc29893dadc89856bcad600dd182d970 100644 --- a/packages/xpub-edit/src/components/Viewer.js +++ b/packages/xpub-edit/src/components/Viewer.js @@ -6,11 +6,11 @@ import baseClasses from 'prosemirror-view/style/prosemirror.css' import classes from './Editor.local.css' class Viewer extends React.Component { - constructor (props) { + constructor(props) { super(props) this.state = { - state: EditorState.create(props.options) + state: EditorState.create(props.options), } } @@ -21,17 +21,13 @@ class Viewer extends React.Component { state, dispatchTransaction: () => false, attributes: { - class: classnames(baseClasses.ProseMirror, classes.ProseMirror) - } + class: classnames(baseClasses.ProseMirror, classes.ProseMirror), + }, }) } - render () { - return ( - <div - ref={this.createEditorView} - /> - ) + render() { + return <div ref={this.createEditorView} /> } } diff --git a/packages/xpub-edit/src/components/Viewer.local.scss b/packages/xpub-edit/src/components/Viewer.local.scss index 746f429b673692c5c8b0290ecb270643370c36d3..391add27092fd0859a145903fdae735928933447 100644 --- a/packages/xpub-edit/src/components/Viewer.local.scss +++ b/packages/xpub-edit/src/components/Viewer.local.scss @@ -1,5 +1,5 @@ .root { + font-family: var(--font-reviewer); font-size: 0.8em; line-height: 1.7; - font-family: var(--font-reviewer); } diff --git a/packages/xpub-edit/src/components/abstract/AbstractEditor.js b/packages/xpub-edit/src/components/abstract/AbstractEditor.js index 0490aa13292bc2432414fa4ae2c53ca103506ca4..ea14634f7bd9795c7c8890468de8e7807127f6d1 100644 --- a/packages/xpub-edit/src/components/abstract/AbstractEditor.js +++ b/packages/xpub-edit/src/components/abstract/AbstractEditor.js @@ -2,16 +2,24 @@ import React from 'react' import HtmlEditor from '../HtmlEditor' import * as options from './config' -const AbstractEditor = ({ className, value, placeholder, placeholderClassName, title, onBlur, onChange }) => ( +const AbstractEditor = ({ + className, + value, + placeholder, + placeholderClassName, + title, + onBlur, + onChange, +}) => ( <HtmlEditor - options={options} - value={value} className={className} + onBlur={onBlur} + onChange={onChange} + options={options} placeholder={placeholder} placeholderClassName={placeholderClassName} title={title} - onBlur={onBlur} - onChange={onChange} + value={value} /> ) diff --git a/packages/xpub-edit/src/components/abstract/AbstractEditor.local.scss b/packages/xpub-edit/src/components/abstract/AbstractEditor.local.scss index b5db4eb25d7a52fccd121a8f3035d366f1f5773a..072c1e640351ad9b644aea60391e8cc256835015 100644 --- a/packages/xpub-edit/src/components/abstract/AbstractEditor.local.scss +++ b/packages/xpub-edit/src/components/abstract/AbstractEditor.local.scss @@ -1,11 +1,11 @@ .root { + font-family: var(--font-author); font-size: 1em; line-height: 1.5; - font-family: var(--font-author); } .placeholder { - font-style: italic; - font-family: var(--font-interface); color: #aaa; + font-family: var(--font-interface); + font-style: italic; } diff --git a/packages/xpub-edit/src/components/abstract/AbstractViewer.js b/packages/xpub-edit/src/components/abstract/AbstractViewer.js index eddbc17765defb53ddab770059c767b5c9d6d6b2..4f4e707b2d8b12b3b61858f1b5b3e7f4e7e5c556 100644 --- a/packages/xpub-edit/src/components/abstract/AbstractViewer.js +++ b/packages/xpub-edit/src/components/abstract/AbstractViewer.js @@ -3,11 +3,7 @@ import HtmlViewer from '../HtmlViewer' import * as options from './config' const AbstractViewer = ({ className, value }) => ( - <HtmlViewer - className={className} - value={value} - options={options} - /> + <HtmlViewer className={className} options={options} value={value} /> ) export default AbstractViewer diff --git a/packages/xpub-edit/src/components/abstract/AbstractViewer.local.scss b/packages/xpub-edit/src/components/abstract/AbstractViewer.local.scss index 8864bf88f5ca551e1376d2917632852bff639068..ed01ce9b592a012e6de43ee8229e7a29c697cfa9 100644 --- a/packages/xpub-edit/src/components/abstract/AbstractViewer.local.scss +++ b/packages/xpub-edit/src/components/abstract/AbstractViewer.local.scss @@ -1,19 +1,14 @@ .root { - min-height: 5em; font-family: var(--font-author); - max-width: 50ch; - text-align: justify; + font-size: 1em; hyphens: auto; line-height: 1.5; + max-width: 50ch; + min-height: 5em; + text-align: justify; } .placeholder { font-family: var(--font-interface); font-style: italic; } - -.root { - font-size: 1em; - line-height: 1.5; - font-family: var(--font-author); -} diff --git a/packages/xpub-edit/src/components/abstract/config/icons.js b/packages/xpub-edit/src/components/abstract/config/icons.js index 98c14f091df2d41fc48b768ecdcc9a23458deeee..83b21279502874cbee04674f86fec850022d7137 100644 --- a/packages/xpub-edit/src/components/abstract/config/icons.js +++ b/packages/xpub-edit/src/components/abstract/config/icons.js @@ -1,11 +1,23 @@ import React from 'react' export default { - italic: <i>Ital</i>, bold: <b>Bold</b>, - superscript: <span>t<sup>x</sup></span>, - subscript: <span>t<sub>x</sub></span>, - small_caps: <span>T<span style={{ fontVariant: 'small-caps', fontSize: '70%' }}>T</span></span>, heading: <span>Section Title</span>, - link: <span>Link</span> + italic: <i>Ital</i>, + link: <span>Link</span>, + small_caps: ( + <span> + T<span style={{ fontSize: '70%', fontVariant: 'small-caps' }}>T</span> + </span> + ), + subscript: ( + <span> + t<sub>x</sub> + </span> + ), + superscript: ( + <span> + t<sup>x</sup> + </span> + ), } diff --git a/packages/xpub-edit/src/components/abstract/config/keys.js b/packages/xpub-edit/src/components/abstract/config/keys.js index ef47f07ee3fad8d02463798fbfcebc9a43e3d5f0..96bd95922928de652706d13f065a69dcc9cf29ab 100644 --- a/packages/xpub-edit/src/components/abstract/config/keys.js +++ b/packages/xpub-edit/src/components/abstract/config/keys.js @@ -1,23 +1,30 @@ import { keymap } from 'prosemirror-keymap' import { undoInputRule } from 'prosemirror-inputrules' import { undo, redo } from 'prosemirror-history' -import { baseKeymap, toggleMark, setBlockType, chainCommands, exitCode, selectParentNode } from 'prosemirror-commands' +import { + baseKeymap, + toggleMark, + setBlockType, + chainCommands, + exitCode, + selectParentNode, +} from 'prosemirror-commands' import schema from './schema' const keys = { - 'Mod-z': undo, - 'Shift-Mod-z': redo, - 'Backspace': undoInputRule, - 'Mod-y': redo, - 'Escape': selectParentNode, + Backspace: undoInputRule, + 'Ctrl-Enter': exitCode, + Escape: selectParentNode, 'Mod-b': toggleMark(schema.marks.bold), - 'Mod-i': toggleMark(schema.marks.italic), 'Mod-Enter': exitCode, - 'Shift-Enter': exitCode, - 'Ctrl-Enter': exitCode, + 'Mod-i': toggleMark(schema.marks.italic), + 'Mod-y': redo, + 'Mod-z': undo, 'Shift-Ctrl-0': setBlockType(schema.nodes.paragraph), - 'Shift-Ctrl-1': setBlockType(schema.nodes.heading, { level: 1 }) + 'Shift-Ctrl-1': setBlockType(schema.nodes.heading, { level: 1 }), + 'Shift-Enter': exitCode, + 'Shift-Mod-z': redo, } Object.keys(baseKeymap).forEach(key => { diff --git a/packages/xpub-edit/src/components/abstract/config/marks.js b/packages/xpub-edit/src/components/abstract/config/marks.js index ad54659cf4fecee1d66c413978d41717991c62e2..5af69382a0b56ca4f464c016e275aeb8d5df4fc3 100644 --- a/packages/xpub-edit/src/components/abstract/config/marks.js +++ b/packages/xpub-edit/src/components/abstract/config/marks.js @@ -1,71 +1,61 @@ const link = { attrs: { href: {}, - title: { default: null } + title: { default: null }, }, inclusive: false, - parseDOM: [{ - tag: 'a[href]', - getAttrs: dom => ({ - href: dom.getAttribute('href'), - title: dom.getAttribute('title') - }) - }], - toDOM: node => ['a', node.attrs] + parseDOM: [ + { + getAttrs: dom => ({ + href: dom.getAttribute('href'), + title: dom.getAttribute('title'), + }), + tag: 'a[href]', + }, + ], + toDOM: node => ['a', node.attrs], } const italic = { - parseDOM: [ - { tag: 'i' }, - { tag: 'em' }, - { style: 'font-style=italic' } - ], - toDOM: () => ['i'] + parseDOM: [{ tag: 'i' }, { tag: 'em' }, { style: 'font-style=italic' }], + toDOM: () => ['i'], } const bold = { parseDOM: [ { tag: 'strong' }, { + getAttrs: node => node.style.fontWeight !== 'normal' && null, tag: 'b', - getAttrs: node => node.style.fontWeight !== 'normal' && null }, { + getAttrs: value => /^(bold(er)?|[5-9]\d{2,})$/.test(value) && null, style: 'font-weight', - getAttrs: value => /^(bold(er)?|[5-9]\d{2,})$/.test(value) && null - } + }, ], - toDOM: () => ['b'] + toDOM: () => ['b'], } const subscript = { - parseDOM: [ - { tag: 'sub' }, - { style: 'vertical-align=sub' } - ], - toDOM: () => ['sub'] + parseDOM: [{ tag: 'sub' }, { style: 'vertical-align=sub' }], + toDOM: () => ['sub'], } const superscript = { - parseDOM: [ - { tag: 'sup' }, - { style: 'vertical-align=super' } - ], - toDOM: () => ['sup'] + parseDOM: [{ tag: 'sup' }, { style: 'vertical-align=super' }], + toDOM: () => ['sup'], } const small_caps = { - parseDOM: [ - { style: 'font-variant=small-caps' } - ], - toDOM: () => ['span', { style: 'font-variant:small-caps' }] + parseDOM: [{ style: 'font-variant=small-caps' }], + toDOM: () => ['span', { style: 'font-variant:small-caps' }], } export default { - link, - italic, bold, + italic, + link, + small_caps, subscript, superscript, - small_caps } diff --git a/packages/xpub-edit/src/components/abstract/config/menu.js b/packages/xpub-edit/src/components/abstract/config/menu.js index dd7fe0c87b045229ad5466ac35d6d8a176700b4b..0763cb8ee054c729ade21eb87ecb3606dc378e15 100644 --- a/packages/xpub-edit/src/components/abstract/config/menu.js +++ b/packages/xpub-edit/src/components/abstract/config/menu.js @@ -22,48 +22,60 @@ const blockActive = (type, attrs = {}) => state => { return to <= $from.end() && $from.parent.hasMarkup(type, attrs) } -const promptForURL = () => { - let url = window.prompt('Enter the URL', 'https://') +// const promptForURL = () => { +// let url = window.prompt('Enter the URL', 'https://') - if (url && !/^https?:\/\//i.test(url)) { - url = 'http://' + url - } +// if (url && !/^https?:\/\//i.test(url)) { +// url = `http://${url}` +// } - return url -} +// return url +// } export default { - marks: { - italic: { - title: 'Toggle italic', - content: icons.italic, - active: markActive(schema.marks.italic), - run: toggleMark(schema.marks.italic) + blocks: { + h1: { + active: blockActive(schema.nodes.heading, { level: 1 }), + content: icons.heading, + enable: setBlockType(schema.nodes.heading, { level: 1 }), + run: (state, dispatch) => { + if (blockActive(schema.marks.heading)(state)) { + setBlockType(schema.marks.paragraph)(state, dispatch) + return true + } + + setBlockType(schema.nodes.heading, { level: 1 })(state, dispatch) + }, + title: 'Change to heading level 1', + }, + }, + history: { + redo: { + content: icons.redo, + enable: redo, + run: redo, + title: 'Redo last undone change', + }, + undo: { + content: icons.undo, + enable: undo, + run: undo, + title: 'Undo last change', }, + }, + marks: { bold: { - title: 'Toggle bold', - content: icons.bold, active: markActive(schema.marks.bold), - run: toggleMark(schema.marks.bold) - }, - subscript: { - title: 'Toggle subscript', - content: icons.subscript, - active: markActive(schema.marks.subscript), - run: toggleMark(schema.marks.subscript) + content: icons.bold, + run: toggleMark(schema.marks.bold), + title: 'Toggle bold', }, - superscript: { - title: 'Toggle superscript', - content: icons.superscript, - active: markActive(schema.marks.superscript), - run: toggleMark(schema.marks.superscript) + italic: { + active: markActive(schema.marks.italic), + content: icons.italic, + run: toggleMark(schema.marks.italic), + title: 'Toggle italic', }, - small_caps: { - title: 'Toggle small caps', - content: icons.small_caps, - active: markActive(schema.marks.small_caps), - run: toggleMark(schema.marks.small_caps) - } // link: { // title: 'Add or remove link', // content: icons.link, @@ -82,35 +94,23 @@ export default { // // view.focus() // } // } - }, - blocks: { - h1: { - title: 'Change to heading level 1', - content: icons.heading, - active: blockActive(schema.nodes.heading, { level: 1 }), - enable: setBlockType(schema.nodes.heading, { level: 1 }), - run: (state, dispatch) => { - if (blockActive(schema.marks.heading)(state)) { - setBlockType(schema.marks.paragraph)(state, dispatch) - return true - } - - setBlockType(schema.nodes.heading, { level: 1 })(state, dispatch) - } - } - }, - history: { - undo: { - title: 'Undo last change', - content: icons.undo, - enable: undo, - run: undo + small_caps: { + active: markActive(schema.marks.small_caps), + content: icons.small_caps, + run: toggleMark(schema.marks.small_caps), + title: 'Toggle small caps', }, - redo: { - title: 'Redo last undone change', - content: icons.redo, - enable: redo, - run: redo - } - } + subscript: { + active: markActive(schema.marks.subscript), + content: icons.subscript, + run: toggleMark(schema.marks.subscript), + title: 'Toggle subscript', + }, + superscript: { + active: markActive(schema.marks.superscript), + content: icons.superscript, + run: toggleMark(schema.marks.superscript), + title: 'Toggle superscript', + }, + }, } diff --git a/packages/xpub-edit/src/components/abstract/config/nodes.js b/packages/xpub-edit/src/components/abstract/config/nodes.js index 710478fa51296409ccbe3bc2819b3dad87031742..13ab00922d753773f59854a52895e1678c887b58 100644 --- a/packages/xpub-edit/src/components/abstract/config/nodes.js +++ b/packages/xpub-edit/src/components/abstract/config/nodes.js @@ -1,36 +1,32 @@ const doc = { - content: 'block+' + content: 'block+', } const paragraph = { content: 'inline*', group: 'block', - parseDOM: [ - { tag: 'p' } - ], - toDOM: () => ['p', 0] + parseDOM: [{ tag: 'p' }], + toDOM: () => ['p', 0], } const heading = { attrs: { - level: { default: 1 } + level: { default: 1 }, }, content: 'inline*', - group: 'block', defining: true, - parseDOM: [ - { tag: 'h1', attrs: { level: 1 } } - ], - toDOM: node => ['h' + node.attrs.level, 0] + group: 'block', + parseDOM: [{ tag: 'h1', attrs: { level: 1 } }], + toDOM: node => [`h${node.attrs.level}`, 0], } const text = { - group: 'inline' + group: 'inline', } export default { doc, - paragraph, heading, - text + paragraph, + text, } diff --git a/packages/xpub-edit/src/components/abstract/config/plugins.js b/packages/xpub-edit/src/components/abstract/config/plugins.js index 5783ee108568c799ab6a366e1fd50b32700dcbba..416cc92326c484dc8ea5f83df90d29220b7cf370 100644 --- a/packages/xpub-edit/src/components/abstract/config/plugins.js +++ b/packages/xpub-edit/src/components/abstract/config/plugins.js @@ -3,9 +3,4 @@ import { dropCursor } from 'prosemirror-dropcursor' import { gapCursor } from 'prosemirror-gapcursor' import keys from './keys' -export default [ - keys, - dropCursor(), - gapCursor(), - history() -] +export default [keys, dropCursor(), gapCursor(), history()] diff --git a/packages/xpub-edit/src/components/abstract/config/schema.js b/packages/xpub-edit/src/components/abstract/config/schema.js index 5a0173ddd31dba187e4bbed9fd7114793555e504..2b1161ddfaf9f0cc7db40a23c525962908d2e30d 100644 --- a/packages/xpub-edit/src/components/abstract/config/schema.js +++ b/packages/xpub-edit/src/components/abstract/config/schema.js @@ -3,4 +3,4 @@ import { Schema } from 'prosemirror-model' import nodes from './nodes' import marks from './marks' -export default new Schema({ nodes, marks }) +export default new Schema({ marks, nodes }) diff --git a/packages/xpub-edit/src/components/note/NoteEditor.js b/packages/xpub-edit/src/components/note/NoteEditor.js index 5922330efefb0bbe4a63027b3b67de22f85e3aa2..9bddee2da20205222297e0ed1a616acc4aadfa9a 100644 --- a/packages/xpub-edit/src/components/note/NoteEditor.js +++ b/packages/xpub-edit/src/components/note/NoteEditor.js @@ -2,16 +2,24 @@ import React from 'react' import HtmlEditor from '../HtmlEditor' import * as options from './config' -const NoteEditor = ({ className, value, placeholder, placeholderClassName, title, onBlur, onChange }) => ( +const NoteEditor = ({ + className, + value, + placeholder, + placeholderClassName, + title, + onBlur, + onChange, +}) => ( <HtmlEditor - options={options} className={className} - value={value} + onBlur={onBlur} + onChange={onChange} + options={options} placeholder={placeholder} placeholderClassName={placeholderClassName} title={title} - onBlur={onBlur} - onChange={onChange} + value={value} /> ) diff --git a/packages/xpub-edit/src/components/note/NoteViewer.js b/packages/xpub-edit/src/components/note/NoteViewer.js index b7a13ee2f23b43e363a371f455cda48eee9d4be8..c9b47a3c916b3bb16aa24226bb47e76183e5500d 100644 --- a/packages/xpub-edit/src/components/note/NoteViewer.js +++ b/packages/xpub-edit/src/components/note/NoteViewer.js @@ -3,11 +3,7 @@ import HtmlViewer from '../HtmlViewer' import * as options from './config' const NoteViewer = ({ className, value }) => ( - <HtmlViewer - className={className} - value={value} - options={options} - /> + <HtmlViewer className={className} options={options} value={value} /> ) export default NoteViewer diff --git a/packages/xpub-edit/src/components/note/config/icons.js b/packages/xpub-edit/src/components/note/config/icons.js index 469207c1a11bbfcae2f12e9a5c8edb237eef968e..0e348d6ccf53d917241b7e2affe9223628984cb0 100644 --- a/packages/xpub-edit/src/components/note/config/icons.js +++ b/packages/xpub-edit/src/components/note/config/icons.js @@ -1,10 +1,22 @@ import React from 'react' export default { - italic: <i>Ital</i>, bold: <b>Bold</b>, - superscript: <span>t<sup>x</sup></span>, - subscript: <span>t<sub>x</sub></span>, - small_caps: <span>T<span style={{ fontVariant: 'small-caps', fontSize: '70%' }}>T</span></span>, - link: <span>Link</span> + italic: <i>Ital</i>, + link: <span>Link</span>, + small_caps: ( + <span> + T<span style={{ fontSize: '70%', fontVariant: 'small-caps' }}>T</span> + </span> + ), + subscript: ( + <span> + t<sub>x</sub> + </span> + ), + superscript: ( + <span> + t<sup>x</sup> + </span> + ), } diff --git a/packages/xpub-edit/src/components/note/config/keys.js b/packages/xpub-edit/src/components/note/config/keys.js index e53625e35512d4456d349dd0da412c0415842248..26b803102714ae65392cc6465cf64a0bc9ab91b0 100644 --- a/packages/xpub-edit/src/components/note/config/keys.js +++ b/packages/xpub-edit/src/components/note/config/keys.js @@ -1,21 +1,27 @@ import { keymap } from 'prosemirror-keymap' import { undoInputRule } from 'prosemirror-inputrules' import { undo, redo } from 'prosemirror-history' -import { baseKeymap, toggleMark, chainCommands, exitCode, selectParentNode } from 'prosemirror-commands' +import { + baseKeymap, + toggleMark, + chainCommands, + exitCode, + selectParentNode, +} from 'prosemirror-commands' import schema from './schema' const keys = { - 'Mod-z': undo, - 'Shift-Mod-z': redo, - 'Backspace': undoInputRule, - 'Mod-y': redo, - 'Escape': selectParentNode, + Backspace: undoInputRule, + 'Ctrl-Enter': exitCode, + Escape: selectParentNode, 'Mod-b': toggleMark(schema.marks.bold), - 'Mod-i': toggleMark(schema.marks.italic), 'Mod-Enter': exitCode, + 'Mod-i': toggleMark(schema.marks.italic), + 'Mod-y': redo, + 'Mod-z': undo, 'Shift-Enter': exitCode, - 'Ctrl-Enter': exitCode + 'Shift-Mod-z': redo, } Object.keys(baseKeymap).forEach(key => { diff --git a/packages/xpub-edit/src/components/note/config/marks.js b/packages/xpub-edit/src/components/note/config/marks.js index ad54659cf4fecee1d66c413978d41717991c62e2..5af69382a0b56ca4f464c016e275aeb8d5df4fc3 100644 --- a/packages/xpub-edit/src/components/note/config/marks.js +++ b/packages/xpub-edit/src/components/note/config/marks.js @@ -1,71 +1,61 @@ const link = { attrs: { href: {}, - title: { default: null } + title: { default: null }, }, inclusive: false, - parseDOM: [{ - tag: 'a[href]', - getAttrs: dom => ({ - href: dom.getAttribute('href'), - title: dom.getAttribute('title') - }) - }], - toDOM: node => ['a', node.attrs] + parseDOM: [ + { + getAttrs: dom => ({ + href: dom.getAttribute('href'), + title: dom.getAttribute('title'), + }), + tag: 'a[href]', + }, + ], + toDOM: node => ['a', node.attrs], } const italic = { - parseDOM: [ - { tag: 'i' }, - { tag: 'em' }, - { style: 'font-style=italic' } - ], - toDOM: () => ['i'] + parseDOM: [{ tag: 'i' }, { tag: 'em' }, { style: 'font-style=italic' }], + toDOM: () => ['i'], } const bold = { parseDOM: [ { tag: 'strong' }, { + getAttrs: node => node.style.fontWeight !== 'normal' && null, tag: 'b', - getAttrs: node => node.style.fontWeight !== 'normal' && null }, { + getAttrs: value => /^(bold(er)?|[5-9]\d{2,})$/.test(value) && null, style: 'font-weight', - getAttrs: value => /^(bold(er)?|[5-9]\d{2,})$/.test(value) && null - } + }, ], - toDOM: () => ['b'] + toDOM: () => ['b'], } const subscript = { - parseDOM: [ - { tag: 'sub' }, - { style: 'vertical-align=sub' } - ], - toDOM: () => ['sub'] + parseDOM: [{ tag: 'sub' }, { style: 'vertical-align=sub' }], + toDOM: () => ['sub'], } const superscript = { - parseDOM: [ - { tag: 'sup' }, - { style: 'vertical-align=super' } - ], - toDOM: () => ['sup'] + parseDOM: [{ tag: 'sup' }, { style: 'vertical-align=super' }], + toDOM: () => ['sup'], } const small_caps = { - parseDOM: [ - { style: 'font-variant=small-caps' } - ], - toDOM: () => ['span', { style: 'font-variant:small-caps' }] + parseDOM: [{ style: 'font-variant=small-caps' }], + toDOM: () => ['span', { style: 'font-variant:small-caps' }], } export default { - link, - italic, bold, + italic, + link, + small_caps, subscript, superscript, - small_caps } diff --git a/packages/xpub-edit/src/components/note/config/menu.js b/packages/xpub-edit/src/components/note/config/menu.js index dd26275b1dd6dc455383ca1a2882e63e38d623d4..45ee363be49130fd150a2efd04bf955c181ff0fa 100644 --- a/packages/xpub-edit/src/components/note/config/menu.js +++ b/packages/xpub-edit/src/components/note/config/menu.js @@ -1,4 +1,4 @@ -import { setBlockType, toggleMark } from 'prosemirror-commands' +import { toggleMark } from 'prosemirror-commands' import { redo, undo } from 'prosemirror-history' import icons from './icons' import schema from './schema' @@ -11,25 +11,25 @@ const markActive = type => state => { : state.doc.rangeHasMark(from, to, type) } -const blockActive = (type, attrs = {}) => state => { - const { $from, to, node } = state.selection +// const blockActive = (type, attrs = {}) => state => { +// const { $from, to, node } = state.selection - if (node) { - return node.hasMarkup(type, attrs) - } +// if (node) { +// return node.hasMarkup(type, attrs) +// } - return to <= $from.end() && $from.parent.hasMarkup(type, attrs) -} +// return to <= $from.end() && $from.parent.hasMarkup(type, attrs) +// } -const promptForURL = () => { - let url = window.prompt('Enter the URL', 'https://') +// const promptForURL = () => { +// let url = window.prompt('Enter the URL', 'https://') - if (url && !/^https?:\/\//i.test(url)) { - url = 'http://' + url - } +// if (url && !/^https?:\/\//i.test(url)) { +// url = `http://${url}` +// } - return url -} +// return url +// } export default { marks: { @@ -37,32 +37,32 @@ export default { title: 'Toggle italic', content: icons.italic, active: markActive(schema.marks.italic), - run: toggleMark(schema.marks.italic) + run: toggleMark(schema.marks.italic), }, bold: { title: 'Toggle bold', content: icons.bold, active: markActive(schema.marks.bold), - run: toggleMark(schema.marks.bold) + run: toggleMark(schema.marks.bold), }, subscript: { title: 'Toggle subscript', content: icons.subscript, active: markActive(schema.marks.subscript), - run: toggleMark(schema.marks.subscript) + run: toggleMark(schema.marks.subscript), }, superscript: { title: 'Toggle superscript', content: icons.superscript, active: markActive(schema.marks.superscript), - run: toggleMark(schema.marks.superscript) + run: toggleMark(schema.marks.superscript), }, small_caps: { title: 'Toggle small caps', content: icons.small_caps, active: markActive(schema.marks.small_caps), - run: toggleMark(schema.marks.small_caps) - } + run: toggleMark(schema.marks.small_caps), + }, // link: { // title: 'Add or remove link', // content: icons.link, @@ -87,13 +87,13 @@ export default { title: 'Undo last change', content: icons.undo, enable: undo, - run: undo + run: undo, }, redo: { title: 'Redo last undone change', content: icons.redo, enable: redo, - run: redo - } - } + run: redo, + }, + }, } diff --git a/packages/xpub-edit/src/components/note/config/nodes.js b/packages/xpub-edit/src/components/note/config/nodes.js index 05fc48d2e1c5c87e3f6822edab881c3da17bd0ae..fe3e083557d1085bfd4bf6ea02a12264665e41fd 100644 --- a/packages/xpub-edit/src/components/note/config/nodes.js +++ b/packages/xpub-edit/src/components/note/config/nodes.js @@ -1,22 +1,20 @@ const doc = { - content: 'block+' + content: 'block+', } const paragraph = { content: 'inline*', group: 'block', - parseDOM: [ - { tag: 'p' } - ], - toDOM: () => ['p', 0] + parseDOM: [{ tag: 'p' }], + toDOM: () => ['p', 0], } const text = { - group: 'inline' + group: 'inline', } export default { doc, paragraph, - text + text, } diff --git a/packages/xpub-edit/src/components/note/config/plugins.js b/packages/xpub-edit/src/components/note/config/plugins.js index 6c0fc8442c360a349ef4e00382bd961552483baf..7679c776a681d8e16e1ad0192cbacbf4004d88f9 100644 --- a/packages/xpub-edit/src/components/note/config/plugins.js +++ b/packages/xpub-edit/src/components/note/config/plugins.js @@ -4,9 +4,4 @@ import { gapCursor } from 'prosemirror-gapcursor' import keys from './keys' -export default [ - keys, - dropCursor(), - gapCursor(), - history() -] +export default [keys, dropCursor(), gapCursor(), history()] diff --git a/packages/xpub-edit/src/components/note/config/schema.js b/packages/xpub-edit/src/components/note/config/schema.js index 5a0173ddd31dba187e4bbed9fd7114793555e504..2b1161ddfaf9f0cc7db40a23c525962908d2e30d 100644 --- a/packages/xpub-edit/src/components/note/config/schema.js +++ b/packages/xpub-edit/src/components/note/config/schema.js @@ -3,4 +3,4 @@ import { Schema } from 'prosemirror-model' import nodes from './nodes' import marks from './marks' -export default new Schema({ nodes, marks }) +export default new Schema({ marks, nodes }) diff --git a/packages/xpub-edit/src/components/text/TextEditor.js b/packages/xpub-edit/src/components/text/TextEditor.js index 00bf53cb326f31ddc4cffcc82ca57c9b308092b3..ceff4e78f6d876e873f6d04b931be9b36a61b988 100644 --- a/packages/xpub-edit/src/components/text/TextEditor.js +++ b/packages/xpub-edit/src/components/text/TextEditor.js @@ -6,16 +6,24 @@ import HtmlEditor from '../HtmlEditor' import * as options from './config' -const TextEditor = ({ className, value, placeholder, placeholderClassName, title, onBlur, onChange }) => ( +const TextEditor = ({ + className, + value, + placeholder, + placeholderClassName, + title, + onBlur, + onChange, +}) => ( <HtmlEditor - options={options} className={className} - value={value} + onBlur={onBlur} + onChange={onChange} + options={options} placeholder={placeholder} placeholderClassName={placeholderClassName} title={title} - onBlur={onBlur} - onChange={onChange} + value={value} /> ) diff --git a/packages/xpub-edit/src/components/text/TextViewer.js b/packages/xpub-edit/src/components/text/TextViewer.js index 30c21d457c743aa5348166694c1e1492b224293c..5ec627f493dad5147ca10bee5f5547b72d0a56a9 100644 --- a/packages/xpub-edit/src/components/text/TextViewer.js +++ b/packages/xpub-edit/src/components/text/TextViewer.js @@ -4,11 +4,7 @@ import HtmlViewer from '../HtmlViewer' import * as options from './config' const TextViewer = ({ className, value }) => ( - <HtmlViewer - className={className} - value={value} - options={options} - /> + <HtmlViewer className={className} options={options} value={value} /> ) export default TextViewer diff --git a/packages/xpub-edit/src/components/text/config/nodes.js b/packages/xpub-edit/src/components/text/config/nodes.js index 05fc48d2e1c5c87e3f6822edab881c3da17bd0ae..fe3e083557d1085bfd4bf6ea02a12264665e41fd 100644 --- a/packages/xpub-edit/src/components/text/config/nodes.js +++ b/packages/xpub-edit/src/components/text/config/nodes.js @@ -1,22 +1,20 @@ const doc = { - content: 'block+' + content: 'block+', } const paragraph = { content: 'inline*', group: 'block', - parseDOM: [ - { tag: 'p' } - ], - toDOM: () => ['p', 0] + parseDOM: [{ tag: 'p' }], + toDOM: () => ['p', 0], } const text = { - group: 'inline' + group: 'inline', } export default { doc, paragraph, - text + text, } diff --git a/packages/xpub-edit/src/components/text/config/plugins.js b/packages/xpub-edit/src/components/text/config/plugins.js index 9af2942c1530285dc1e31e740e25e40defc42b0c..43ccb6f67d6310a6f44e6df9fd50afe966e5683e 100644 --- a/packages/xpub-edit/src/components/text/config/plugins.js +++ b/packages/xpub-edit/src/components/text/config/plugins.js @@ -1,5 +1,3 @@ import { history } from 'prosemirror-history' -export default [ - history() -] +export default [history()] diff --git a/packages/xpub-edit/src/components/text/config/schema.js b/packages/xpub-edit/src/components/text/config/schema.js index e5ee6b9635472f729a6ad8f117e82e3a3488fa99..3a13a3861363d3acf6ec620249b2869ddc179536 100644 --- a/packages/xpub-edit/src/components/text/config/schema.js +++ b/packages/xpub-edit/src/components/text/config/schema.js @@ -4,4 +4,4 @@ import nodes from './nodes' const marks = {} -export default new Schema({ nodes, marks }) +export default new Schema({ marks, nodes }) diff --git a/packages/xpub-edit/src/components/title/TitleEditor.js b/packages/xpub-edit/src/components/title/TitleEditor.js index 5e05176f04888d2af9b33f3f2281f1642b1a5229..fc10ccda8ee4e7d40102271e880ed47d23f1d1f7 100644 --- a/packages/xpub-edit/src/components/title/TitleEditor.js +++ b/packages/xpub-edit/src/components/title/TitleEditor.js @@ -2,16 +2,24 @@ import React from 'react' import HtmlEditor from '../HtmlEditor' import * as options from './config' -const TitleEditor = ({ className, value, placeholder, placeholderClassName, title, onBlur, onChange }) => ( +const TitleEditor = ({ + className, + value, + placeholder, + placeholderClassName, + title, + onBlur, + onChange, +}) => ( <HtmlEditor - options={options} className={className} - value={value} + onBlur={onBlur} + onChange={onChange} + options={options} placeholder={placeholder} placeholderClassName={placeholderClassName} title={title} - onBlur={onBlur} - onChange={onChange} + value={value} /> ) diff --git a/packages/xpub-edit/src/components/title/TitleViewer.js b/packages/xpub-edit/src/components/title/TitleViewer.js index 0caeb2732ad8173e509ade71690b0828755d5031..d73bb2b7eb7c8bc80d1eb68c219f682c97e5e78d 100644 --- a/packages/xpub-edit/src/components/title/TitleViewer.js +++ b/packages/xpub-edit/src/components/title/TitleViewer.js @@ -3,11 +3,7 @@ import HtmlViewer from '../HtmlViewer' import * as options from './config' const TitleViewer = ({ className, value }) => ( - <HtmlViewer - options={options} - className={className} - value={value} - /> + <HtmlViewer className={className} options={options} value={value} /> ) export default TitleViewer diff --git a/packages/xpub-edit/src/components/title/TitleViewer.local.scss b/packages/xpub-edit/src/components/title/TitleViewer.local.scss index b81a77a39bfd309362832277c8b35d6d044b5299..cedfad6a2150685fbd9d42eea215a13eb090e966 100644 --- a/packages/xpub-edit/src/components/title/TitleViewer.local.scss +++ b/packages/xpub-edit/src/components/title/TitleViewer.local.scss @@ -1,6 +1,6 @@ .root { display: inline-block; - margin-top: 0; - margin-bottom: 0; font-family: var(--font-author) !important; + margin-bottom: 0; + margin-top: 0; } diff --git a/packages/xpub-edit/src/components/title/config/icons.js b/packages/xpub-edit/src/components/title/config/icons.js index 140886ed4fd925b13775a7d6c51a5fc8c5dda5d2..df1f1d484967ef41085365c69bf84a60212ab595 100644 --- a/packages/xpub-edit/src/components/title/config/icons.js +++ b/packages/xpub-edit/src/components/title/config/icons.js @@ -2,7 +2,19 @@ import React from 'react' export default { italic: <i>Ital</i>, - superscript: <span>t<sup>x</sup></span>, - subscript: <span>t<sub>x</sub></span>, - small_caps: <span>T<span style={{ fontVariant: 'small-caps', fontSize: '70%' }}>T</span></span> + small_caps: ( + <span> + T<span style={{ fontSize: '70%', fontVariant: 'small-caps' }}>T</span> + </span> + ), + subscript: ( + <span> + t<sub>x</sub> + </span> + ), + superscript: ( + <span> + t<sup>x</sup> + </span> + ), } diff --git a/packages/xpub-edit/src/components/title/config/keys.js b/packages/xpub-edit/src/components/title/config/keys.js index ca0acd42bd2aa085a55957bd3c8227a0e341472b..620a35d9467759b588e1d0477c394644c787f9c2 100644 --- a/packages/xpub-edit/src/components/title/config/keys.js +++ b/packages/xpub-edit/src/components/title/config/keys.js @@ -6,11 +6,11 @@ import { baseKeymap, toggleMark, chainCommands } from 'prosemirror-commands' import schema from './schema' const keys = { + Backspace: undoInputRule, + 'Mod-i': toggleMark(schema.marks.italic), + 'Mod-y': redo, 'Mod-z': undo, 'Shift-Mod-z': redo, - 'Backspace': undoInputRule, - 'Mod-y': redo, - 'Mod-i': toggleMark(schema.marks.italic) } Object.keys(baseKeymap).forEach(key => { diff --git a/packages/xpub-edit/src/components/title/config/marks.js b/packages/xpub-edit/src/components/title/config/marks.js index 6a0db1a4dad7c325852511a3fb7e6c8cc39e8843..4eec3d32c63246eb044ca7fd3196c57aab93f9d0 100644 --- a/packages/xpub-edit/src/components/title/config/marks.js +++ b/packages/xpub-edit/src/components/title/config/marks.js @@ -1,38 +1,26 @@ const italic = { - parseDOM: [ - { tag: 'i' }, - { tag: 'em' }, - { style: 'font-style=italic' } - ], - toDOM: () => ['i'] + parseDOM: [{ tag: 'i' }, { tag: 'em' }, { style: 'font-style=italic' }], + toDOM: () => ['i'], } const subscript = { - parseDOM: [ - { tag: 'sub' }, - { style: 'vertical-align=sub' } - ], - toDOM: () => ['sub'] + parseDOM: [{ tag: 'sub' }, { style: 'vertical-align=sub' }], + toDOM: () => ['sub'], } const superscript = { - parseDOM: [ - { tag: 'sup' }, - { style: 'vertical-align=super' } - ], - toDOM: () => ['sup'] + parseDOM: [{ tag: 'sup' }, { style: 'vertical-align=super' }], + toDOM: () => ['sup'], } const small_caps = { - parseDOM: [ - { style: 'font-variant=small-caps' } - ], - toDOM: () => ['span', { style: 'font-variant:small-caps' }] + parseDOM: [{ style: 'font-variant=small-caps' }], + toDOM: () => ['span', { style: 'font-variant:small-caps' }], } export default { italic, + small_caps, subscript, superscript, - small_caps } diff --git a/packages/xpub-edit/src/components/title/config/menu.js b/packages/xpub-edit/src/components/title/config/menu.js index 3d802a69ccf0b16f067cb0f505ed05bf392aa66b..4edbe4a7060669a806c0380dbfd7d6aba25ee984 100644 --- a/packages/xpub-edit/src/components/title/config/menu.js +++ b/packages/xpub-edit/src/components/title/config/menu.js @@ -14,28 +14,28 @@ const markActive = type => state => { export default { marks: { italic: { - title: 'Toggle italic', - content: icons.italic, active: markActive(schema.marks.italic), - run: toggleMark(schema.marks.italic) + content: icons.italic, + run: toggleMark(schema.marks.italic), + title: 'Toggle italic', + }, + small_caps: { + active: markActive(schema.marks.small_caps), + content: icons.small_caps, + run: toggleMark(schema.marks.small_caps), + title: 'Toggle small caps', }, subscript: { - title: 'Toggle subscript', - content: icons.subscript, active: markActive(schema.marks.subscript), - run: toggleMark(schema.marks.subscript) + content: icons.subscript, + run: toggleMark(schema.marks.subscript), + title: 'Toggle subscript', }, superscript: { - title: 'Toggle superscript', - content: icons.superscript, active: markActive(schema.marks.superscript), - run: toggleMark(schema.marks.superscript) + content: icons.superscript, + run: toggleMark(schema.marks.superscript), + title: 'Toggle superscript', }, - small_caps: { - title: 'Toggle small caps', - content: icons.small_caps, - active: markActive(schema.marks.small_caps), - run: toggleMark(schema.marks.small_caps) - } - } + }, } diff --git a/packages/xpub-edit/src/components/title/config/nodes.js b/packages/xpub-edit/src/components/title/config/nodes.js index 05fc48d2e1c5c87e3f6822edab881c3da17bd0ae..fe3e083557d1085bfd4bf6ea02a12264665e41fd 100644 --- a/packages/xpub-edit/src/components/title/config/nodes.js +++ b/packages/xpub-edit/src/components/title/config/nodes.js @@ -1,22 +1,20 @@ const doc = { - content: 'block+' + content: 'block+', } const paragraph = { content: 'inline*', group: 'block', - parseDOM: [ - { tag: 'p' } - ], - toDOM: () => ['p', 0] + parseDOM: [{ tag: 'p' }], + toDOM: () => ['p', 0], } const text = { - group: 'inline' + group: 'inline', } export default { doc, paragraph, - text + text, } diff --git a/packages/xpub-edit/src/components/title/config/plugins.js b/packages/xpub-edit/src/components/title/config/plugins.js index b21e5912131fd29d5cb64d15179a3bc804c42341..1076108f7c38f26e133144ee8f9a735ef6a2982e 100644 --- a/packages/xpub-edit/src/components/title/config/plugins.js +++ b/packages/xpub-edit/src/components/title/config/plugins.js @@ -2,7 +2,4 @@ import { history } from 'prosemirror-history' import keys from './keys' -export default [ - keys, - history() -] +export default [keys, history()] diff --git a/packages/xpub-edit/src/components/title/config/schema.js b/packages/xpub-edit/src/components/title/config/schema.js index 5a0173ddd31dba187e4bbed9fd7114793555e504..2b1161ddfaf9f0cc7db40a23c525962908d2e30d 100644 --- a/packages/xpub-edit/src/components/title/config/schema.js +++ b/packages/xpub-edit/src/components/title/config/schema.js @@ -3,4 +3,4 @@ import { Schema } from 'prosemirror-model' import nodes from './nodes' import marks from './marks' -export default new Schema({ nodes, marks }) +export default new Schema({ marks, nodes }) diff --git a/packages/xpub-edit/src/decorations.js b/packages/xpub-edit/src/decorations.js index fe8777480db63128b57e7395981d75e7c272085e..221da8dfe744f83b51e10a309cc564ca56087d24 100644 --- a/packages/xpub-edit/src/decorations.js +++ b/packages/xpub-edit/src/decorations.js @@ -1,14 +1,15 @@ import { DecorationSet, Decoration } from 'prosemirror-view' export default ({ props, classes }) => state => { - const doc = state.doc + const { doc } = state const decorations = [] - if (props.placeholder && + if ( + props.placeholder && doc.childCount === 1 && doc.firstChild.isTextblock && - doc.firstChild.content.size === 0) { - + doc.firstChild.content.size === 0 + ) { const placeHolder = document.createElement('div') placeHolder.textContent = props.placeholder placeHolder.classList.add(classes.placeholder) diff --git a/packages/xpub-edit/styleguide.config.js b/packages/xpub-edit/styleguide.config.js index 203f8d5f2fa1eef23f7b84ce56b5f8405267b159..b67773b617e1dd72514198951e0b24046d9c5cc8 100644 --- a/packages/xpub-edit/styleguide.config.js +++ b/packages/xpub-edit/styleguide.config.js @@ -1,20 +1,22 @@ module.exports = { - title: 'xpub-edit style guide', - styleguideComponents: { - StyleGuideRenderer: require.resolve('xpub-styleguide/src/components/StyleGuideRenderer'), - Wrapper: require.resolve('xpub-styleguide/src/components/Wrapper') + context: { + faker: 'faker', }, serverPort: 6066, skipComponentsWithoutExample: true, - context: { - faker: 'faker' + styleguideComponents: { + StyleGuideRenderer: require.resolve( + 'xpub-styleguide/src/components/StyleGuideRenderer', + ), + Wrapper: require.resolve('xpub-styleguide/src/components/Wrapper'), }, theme: { + color: { + link: 'cornflowerblue', + }, fontFamily: { - base: '"Fira Sans", sans-serif' + base: '"Fira Sans", sans-serif', }, - color: { - link: 'cornflowerblue' - } - } + }, + title: 'xpub-edit style guide', } diff --git a/packages/xpub-journal/src/components/JournalProvider.js b/packages/xpub-journal/src/components/JournalProvider.js index 4473b85c4eb9f6269bb23c3639329db0992cd5d8..28328034957f4a7800b1059b3dfbd7f683bf255d 100644 --- a/packages/xpub-journal/src/components/JournalProvider.js +++ b/packages/xpub-journal/src/components/JournalProvider.js @@ -4,9 +4,9 @@ import { withContext, getContext } from 'recompose' export const JournalProvider = withContext( { journal: PropTypes.object }, - ({ journal }) => ({ journal }) + ({ journal }) => ({ journal }), )(props => React.Children.only(props.children)) export const withJournal = getContext({ - journal: PropTypes.object + journal: PropTypes.object, }) diff --git a/packages/xpub-selectors/src/index.js b/packages/xpub-selectors/src/index.js index fbf3714ebfb37ec43d1fdd8d402a00ae1768631f..c6df763d95d2369aaaecc006d9cbcd02259ecc9e 100644 --- a/packages/xpub-selectors/src/index.js +++ b/packages/xpub-selectors/src/index.js @@ -2,36 +2,33 @@ import { orderBy } from 'lodash' export const newestFirst = items => orderBy(items, ['created'], ['desc']) -export const selectCurrentUser = state => state.currentUser.isAuthenticated - ? state.currentUser.user - : null +export const selectCurrentUser = state => + state.currentUser.isAuthenticated ? state.currentUser.user : null // TODO: collections should be keyed by id -export const selectCollection = (state, id) => state.collections - .find(collection => collection.id === id) +export const selectCollection = (state, id) => + state.collections.find(collection => collection.id === id) // TODO: there shouldn't be any missing -export const selectFragments = (state, ids) => ids - .map(id => state.fragments[id]) - .filter(fragment => fragment) +export const selectFragments = (state, ids) => + ids.map(id => state.fragments[id]).filter(fragment => fragment) export const selectFragment = (state, id) => state.fragments[id] -export const selectCurrentVersion = (state, project) => { - return newestFirst(selectFragments(state, project.fragments))[0] -} +export const selectCurrentVersion = (state, project) => + newestFirst(selectFragments(state, project.fragments))[0] export const getReviewerFromUser = (project, version, currentUser) => { if (!project.reviewers || !version.reviewers) return null const projectReviewer = project.reviewers.find( - reviewer => reviewer && reviewer.user === currentUser.id + reviewer => reviewer && reviewer.user === currentUser.id, ) return version.reviewers.find( - reviewer => reviewer && reviewer.reviewer === projectReviewer.id + reviewer => reviewer && reviewer.reviewer === projectReviewer.id, ) } -export const selectUser = (state, id) => state.users.users - .find(user => user.id === id) +export const selectUser = (state, id) => + state.users.users.find(user => user.id === id) diff --git a/packages/xpub-styleguide/src/components/StyleGuideRenderer.js b/packages/xpub-styleguide/src/components/StyleGuideRenderer.js index 706cbd1049ec5e95494b364765c842f5c0bc077b..b1a65700dfd22533f14e9ac59fc07e47849c3114 100644 --- a/packages/xpub-styleguide/src/components/StyleGuideRenderer.js +++ b/packages/xpub-styleguide/src/components/StyleGuideRenderer.js @@ -1,24 +1,18 @@ import React from 'react' import classes from './StyleGuideRenderer.local.scss' -const StyleGuideRenderer = ({ title, children, toc }) => { - return ( - <div className={classes.root}> - <div className={classes.sidebar}> - <header className={classes.header}> - <h1 className={classes.title}>{title}</h1> - </header> +const StyleGuideRenderer = ({ title, children, toc }) => ( + <div className={classes.root}> + <div className={classes.sidebar}> + <header className={classes.header}> + <h1 className={classes.title}>{title}</h1> + </header> - <nav className={classes.nav}> - {toc} - </nav> - </div> - - <div className={classes.content}> - {children} - </div> + <nav className={classes.nav}>{toc}</nav> </div> - ) -} + + <div className={classes.content}>{children}</div> + </div> +) export default StyleGuideRenderer diff --git a/packages/xpub-styleguide/src/components/StyleGuideRenderer.local.scss b/packages/xpub-styleguide/src/components/StyleGuideRenderer.local.scss index 67dae5dd76d706fad18b063b3f0a548c3e93968b..bdd3e8097da381478d55ed6ac804cf701de0422d 100644 --- a/packages/xpub-styleguide/src/components/StyleGuideRenderer.local.scss +++ b/packages/xpub-styleguide/src/components/StyleGuideRenderer.local.scss @@ -1,22 +1,22 @@ .root { display: grid; - grid-template-columns: 1fr 3fr; grid-template-areas: "side content"; + grid-template-columns: 1fr 3fr; height: 100vh; width: 100vw; } .sidebar { - grid-area: side; display: flex; flex-direction: column; + grid-area: side; overflow-y: hidden; } .content { grid-area: content; - padding: 1rem; overflow-y: auto; + padding: 1rem; } .header { diff --git a/packages/xpub-styleguide/src/components/Wrapper.js b/packages/xpub-styleguide/src/components/Wrapper.js index 5055f8119be84402d3f3ab633304924cb8d20d44..b0df3e215880398c8f3c948ea2d3cab36ac5b270 100644 --- a/packages/xpub-styleguide/src/components/Wrapper.js +++ b/packages/xpub-styleguide/src/components/Wrapper.js @@ -4,28 +4,27 @@ import { BrowserRouter as Router } from 'react-router-dom' import { reducer as formReducer } from 'redux-form' import { createStore, combineReducers } from 'redux' import { JournalProvider } from 'xpub-journal' -import * as journal from '../config/journal' import 'xpub-theme' +import * as journal from '../config/journal' + import classes from './Wrapper.local.scss' const rootReducer = combineReducers({ - form: formReducer + form: formReducer, }) const store = createStore( rootReducer, - window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() + window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(), ) const Wrapper = ({ children }) => ( <Provider store={store}> <Router> <JournalProvider journal={journal}> - <div className={classes.root}> - {children} - </div> + <div className={classes.root}>{children}</div> </JournalProvider> </Router> </Provider> diff --git a/packages/xpub-styleguide/src/components/index.js b/packages/xpub-styleguide/src/components/index.js index 51df89d7483ed44e9d17ddf3eda90148155e2869..6c609447f503d184ae88fb2abd76b6cd9eba9690 100644 --- a/packages/xpub-styleguide/src/components/index.js +++ b/packages/xpub-styleguide/src/components/index.js @@ -1,4 +1,4 @@ module.exports = { StyleGuideRenderer: require('./StyleGuideRenderer'), - Wrapper: require('./Wrapper') + Wrapper: require('./Wrapper'), } diff --git a/packages/xpub-styleguide/src/config/journal/article-sections.js b/packages/xpub-styleguide/src/config/journal/article-sections.js index 3f797b098741359ce4f54e473919585a2f64189a..f258a498836451ea9f6b30abf64b44a2bf4c6c47 100644 --- a/packages/xpub-styleguide/src/config/journal/article-sections.js +++ b/packages/xpub-styleguide/src/config/journal/article-sections.js @@ -1,30 +1,30 @@ export default [ { value: 'cognitive-psychology', - label: 'Cognitive Psychology' + label: 'Cognitive Psychology', }, { value: 'social-psychology', - label: 'Social Psychology' + label: 'Social Psychology', }, { value: 'personality-psychology', - label: 'Personality Psychology' + label: 'Personality Psychology', }, { value: 'developmental-psychology', - label: 'Developmental Psychology' + label: 'Developmental Psychology', }, { value: 'clinical-psychology', - label: 'Clinical Psychology' + label: 'Clinical Psychology', }, { value: 'organizational-behavior', - label: 'Organizational Behavior' + label: 'Organizational Behavior', }, { value: 'methodology', - label: 'Methodology and Research Practice' + label: 'Methodology and Research Practice', }, ] diff --git a/packages/xpub-styleguide/src/config/journal/article-types.js b/packages/xpub-styleguide/src/config/journal/article-types.js index 9a456260fc2644fa543b90bed5bb351af41f14bb..bdaa9f9e39346a55815221a86b57050db13a97ac 100644 --- a/packages/xpub-styleguide/src/config/journal/article-types.js +++ b/packages/xpub-styleguide/src/config/journal/article-types.js @@ -1,18 +1,18 @@ export default [ { value: 'original-research', - label: 'Original Research Report' + label: 'Original Research Report', }, { value: 'review', - label: 'Review' + label: 'Review', }, { value: 'opinion', - label: 'Opinion/Commentary' + label: 'Opinion/Commentary', }, { value: 'registered-report', - label: 'Registered Report' + label: 'Registered Report', }, ] diff --git a/packages/xpub-styleguide/src/config/journal/decisions.js b/packages/xpub-styleguide/src/config/journal/decisions.js index 7b9e6dabf698f0ab0c07537a724679d6d8db7b41..6a91c806aee2ea843eaa301739387e7522a103de 100644 --- a/packages/xpub-styleguide/src/config/journal/decisions.js +++ b/packages/xpub-styleguide/src/config/journal/decisions.js @@ -2,21 +2,22 @@ export default { accept: { label: 'Accept', color: 'green', - message: 'The submission has been accepted for publication' + message: 'The submission has been accepted for publication', }, minor: { label: 'Minor revisions', color: 'orange', - message: 'The submission will be accepted for publication after minor changes' + message: + 'The submission will be accepted for publication after minor changes', }, major: { label: 'Major revisions', color: 'yellow', - message: 'The requested changes must be made before submission for review' + message: 'The requested changes must be made before submission for review', }, reject: { label: 'Reject', color: 'red', - message: 'The submission is not acceptable for publication' + message: 'The submission is not acceptable for publication', }, } diff --git a/packages/xpub-styleguide/src/config/journal/declarations.js b/packages/xpub-styleguide/src/config/journal/declarations.js index 803db14edec42d89c903fbade1f6c6943def29fc..012e4d46c2bfe3b20da969a9277a391d61c18094 100644 --- a/packages/xpub-styleguide/src/config/journal/declarations.js +++ b/packages/xpub-styleguide/src/config/journal/declarations.js @@ -2,27 +2,27 @@ export default { questions: [ { id: 'openData', - legend: 'Data is open' + legend: 'Data is open', }, { id: 'previouslySubmitted', - legend: 'Previously submitted' + legend: 'Previously submitted', }, { id: 'openPeerReview', - legend: 'Open peer review' + legend: 'Open peer review', }, { id: 'streamlinedReview', - legend: 'Streamlined review' + legend: 'Streamlined review', }, { id: 'researchNexus', - legend: 'Submitted as part of the research nexus?' + legend: 'Submitted as part of the research nexus?', }, { id: 'preregistered', - legend: 'Pre-registered?' - } - ] + legend: 'Pre-registered?', + }, + ], } diff --git a/packages/xpub-styleguide/src/config/journal/editors.js b/packages/xpub-styleguide/src/config/journal/editors.js index a3af69f0bba715db1f757b70efa0a37b6e755519..e19de06a9df69826e9e7667f9ff7d4d2ca44944f 100644 --- a/packages/xpub-styleguide/src/config/journal/editors.js +++ b/packages/xpub-styleguide/src/config/journal/editors.js @@ -2,31 +2,31 @@ export default { managingEditor: [ { user: 1, - name: "Managing Editor One" + name: 'Managing Editor One', }, { user: 2, - name: "Managing Editor Two" - } + name: 'Managing Editor Two', + }, ], seniorEditor: [ { user: 3, - name: "Senior Editor One" + name: 'Senior Editor One', }, { user: 4, - name: "Senior Editor Two" - } + name: 'Senior Editor Two', + }, ], handlingEditor: [ { user: 5, - name: "Handling Editor One" + name: 'Handling Editor One', }, { user: 6, - name: "Handling Editor Two" - } - ] + name: 'Handling Editor Two', + }, + ], } diff --git a/packages/xpub-styleguide/src/config/journal/metadata.js b/packages/xpub-styleguide/src/config/journal/metadata.js index db9d6d8e0070761bb9f75849d9db540cda6fa7c7..940970ae1d4d51ac0889b940344d453af3e48360 100644 --- a/packages/xpub-styleguide/src/config/journal/metadata.js +++ b/packages/xpub-styleguide/src/config/journal/metadata.js @@ -1,4 +1,4 @@ export default { name: 'Example Journal', - issn: '1234-1234' + issn: '1234-1234', } diff --git a/packages/xpub-styleguide/src/config/journal/recommendations.js b/packages/xpub-styleguide/src/config/journal/recommendations.js index e62b4f88c51cc6dfaf15d74bb21edf0e4281e93e..ad4a252206cd22d092ada66a38271ab86881f2c9 100644 --- a/packages/xpub-styleguide/src/config/journal/recommendations.js +++ b/packages/xpub-styleguide/src/config/journal/recommendations.js @@ -2,16 +2,16 @@ export default [ { value: 'accept', label: 'Accept', - color: 'green' + color: 'green', }, { value: 'revise', label: 'Revise', - color: 'orange' + color: 'orange', }, { value: 'reject', label: 'Reject', - color: 'red' - } + color: 'red', + }, ] diff --git a/packages/xpub-styleguide/src/config/journal/roles.js b/packages/xpub-styleguide/src/config/journal/roles.js index 17420307448c51618a351691035b55a7b6007a92..0f9334d4c66a69a75359e50150a8f7b40f153ee6 100644 --- a/packages/xpub-styleguide/src/config/journal/roles.js +++ b/packages/xpub-styleguide/src/config/journal/roles.js @@ -1,6 +1,6 @@ export default { author: 'Author', - seniorEditor: 'Senior Editor', - managingEditor: 'Managing Editor', handlingEditor: 'Handling Editor', + managingEditor: 'Managing Editor', + seniorEditor: 'Senior Editor', } diff --git a/packages/xpub-styleguide/src/config/journal/sections.js b/packages/xpub-styleguide/src/config/journal/sections.js index 419171898b0abb22f9c5917684de31809de75cb2..72bbd760b76499147343cb51e9a73954f71eade3 100644 --- a/packages/xpub-styleguide/src/config/journal/sections.js +++ b/packages/xpub-styleguide/src/config/journal/sections.js @@ -1,6 +1,6 @@ export default [ { id: 'submissions', - label: 'My Submissions' - } + label: 'My Submissions', + }, ] diff --git a/packages/xpub-styleguide/src/webpack-config.js b/packages/xpub-styleguide/src/webpack-config.js index ba303b856e437b218dec9c8007b70ae3cd4634b7..71c81cef1c423f1a706dd4cc76ce5f07cc55a936 100644 --- a/packages/xpub-styleguide/src/webpack-config.js +++ b/packages/xpub-styleguide/src/webpack-config.js @@ -11,26 +11,15 @@ module.exports = dir => { /pubsweet-[^/]+\/src/, /xpub-[^/]+\/src/, /wax-[^/]+\/src/, - /@pubsweet\/[^/]+\/src/ + /@pubsweet\/[^/]+\/src/, ] return { - entry: './src/index.js', - output: { - filename: 'index.js', - path: path.join(dir, 'dist') - }, devtool: 'cheap-module-source-map', - watch: true, + entry: './src/index.js', // externals: [nodeExternals({ // whitelist: [/\.(?!js$).{1,5}$/i] // })], - plugins: [ - // mock constants - new webpack.DefinePlugin({ - PUBSWEET_COMPONENTS: '[]' - }), - ], module: { rules: [ { @@ -44,7 +33,7 @@ module.exports = dir => { presets: [ [require('babel-preset-env'), { modules: false }], require('babel-preset-react'), - require('babel-preset-stage-2') + require('babel-preset-stage-2'), ], cacheDirectory: true, }, @@ -62,8 +51,8 @@ module.exports = dir => { modules: true, // sourceMap: true, localIdentName: '[name]_[local]-[hash:base64:8]', - } - } + }, + }, ], }, @@ -80,19 +69,16 @@ module.exports = dir => { importLoaders: 1, // sourceMap: true, localIdentName: '[name]_[local]-[hash:base64:8]', - } + }, }, - 'sass-loader' + 'sass-loader', ], }, // global CSS { test: /\.css$/, - use: [ - 'style-loader', - 'css-loader' - ] + use: ['style-loader', 'css-loader'], }, // global SCSS @@ -107,8 +93,8 @@ module.exports = dir => { // importLoaders: 1, // } // }, - 'sass-loader' - ] + 'sass-loader', + ], }, // Files @@ -117,11 +103,22 @@ module.exports = dir => { loader: 'file-loader', options: { name: 'static/media/[name].[hash:8].[ext]', - } - } - ] - } - ] - } + }, + }, + ], + }, + ], + }, + output: { + filename: 'index.js', + path: path.join(dir, 'dist'), + }, + plugins: [ + // mock constants + new webpack.DefinePlugin({ + PUBSWEET_COMPONENTS: '[]', + }), + ], + watch: true, } } diff --git a/packages/xpub-ui/package.json b/packages/xpub-ui/package.json index fb89d31488c7abba53bafcb9e95e20aba1a5f8d5..13126a9fccaec1bedccc3145f7fb9fbaa0056c3f 100644 --- a/packages/xpub-ui/package.json +++ b/packages/xpub-ui/package.json @@ -9,7 +9,11 @@ "main": "src", "jsnext:main": "src", "dependencies": { + "babel-jest": "^21.2.0", "classnames": "^2.2.5", + "enzyme": "^3.2.0", + "enzyme-adapter-react-15": "^1.0.5", + "lodash": "^4.17.4", "humps": "^2.0.1", "prop-types": "^15.5.10", "react": "^15.6.1", @@ -24,14 +28,11 @@ }, "devDependencies": { "babel-core": "^6.26.0", - "babel-jest": "^21.2.0", "babel-loader": "^7.1.2", "babel-preset-env": "^1.6.0", "babel-preset-react": "^6.24.1", "babel-preset-stage-2": "^6.24.1", "css-loader": "^0.28.4", - "enzyme": "^3.2.0", - "enzyme-adapter-react-15": "^1.0.5", "faker": "^4.1.0", "file-loader": "^1.1.5", "identity-obj-proxy": "^3.0.0", diff --git a/packages/xpub-ui/src/atoms/Attachment.js b/packages/xpub-ui/src/atoms/Attachment.js index 2afd1925ea5fb2f6f06edb8df369e37b0aa269dc..9f9be1d4982afa1ac866ecaf7c6ab965693612f6 100644 --- a/packages/xpub-ui/src/atoms/Attachment.js +++ b/packages/xpub-ui/src/atoms/Attachment.js @@ -3,15 +3,11 @@ import Icon from './Icon' import classes from './Attachment.local.scss' const Attachment = ({ value }) => ( - <a - download={value.name} - href={value.url}> + <a download={value.name} href={value.url}> <span className={classes.icon}> <Icon color="var(--color-primary)">paperclip</Icon> </span> - <span className={classes.filename}> - {value.name} - </span> + <span className={classes.filename}>{value.name}</span> </a> ) diff --git a/packages/xpub-ui/src/atoms/Attachment.local.scss b/packages/xpub-ui/src/atoms/Attachment.local.scss index c60f144daa7aabbd9c72b8c1cd6c180acc645299..4a6f520208438c03d42cdc043dfd0b51e284112d 100644 --- a/packages/xpub-ui/src/atoms/Attachment.local.scss +++ b/packages/xpub-ui/src/atoms/Attachment.local.scss @@ -1,13 +1,13 @@ .icon { - margin-right: 10px; - display: inline-flex; color: var(--color-primary); + display: inline-flex; + margin-right: 10px; } .filename { font-size: 0.7em; - max-width: 25ch; height: 2em; + max-width: 25ch; overflow-wrap: break-word; padding: 0; } diff --git a/packages/xpub-ui/src/atoms/Avatar.js b/packages/xpub-ui/src/atoms/Avatar.js index d90c97697d979901bb0bfcefb5277ee96eba81a7..d30de999d717c895bce2afb93ef35a5877afd533 100644 --- a/packages/xpub-ui/src/atoms/Avatar.js +++ b/packages/xpub-ui/src/atoms/Avatar.js @@ -8,10 +8,10 @@ const Avatar = ({ status, width, height, reviewerLetter }) => { return ( <svg className={classes[classValue]} + height={height || '70'} + viewBox={`0 0 ${width ? width + 5 : '105'} ${height || '70'}`} + width={width || '100'} xmlns="http://www.w3.org/2000/svg" - viewBox={`0 0 ${width ? width + 5 : '105'} ${height ? height : '70'}`} - width={width ? width : '100'} - height={height ? height : '70'} > <path className={classes.persona} diff --git a/packages/xpub-ui/src/atoms/Avatar.local.scss b/packages/xpub-ui/src/atoms/Avatar.local.scss index 4442aefc849b106dca0b05b3393e0f3c73102314..9ff6dfcf5eb84c71ce575f2f439da0e92fd5802a 100644 --- a/packages/xpub-ui/src/atoms/Avatar.local.scss +++ b/packages/xpub-ui/src/atoms/Avatar.local.scss @@ -1,20 +1,20 @@ figure { - width: auto; margin: 0 auto 2px; text-align: center; + width: auto; } svg { + height: auto; + max-height: 100vh; max-width: 100%; width: auto; - max-height: 100vh; - height: auto; } .default { .persona { - fill: var(--color-primary); display: block; + fill: var(--color-primary); } .check { @@ -36,13 +36,13 @@ svg { .accepted { .persona { - fill: var(--color-primary); display: block; + fill: var(--color-primary); } .check { - fill: var(--color-primary); display: block; + fill: var(--color-primary); } .x { @@ -60,8 +60,8 @@ svg { .declined { .persona { - fill: var(--color-danger); display: block; + fill: var(--color-danger); } .check { @@ -69,8 +69,8 @@ svg { } .x { - fill: var(--color-danger); display: block; + fill: var(--color-danger); } .question-mark { @@ -84,8 +84,8 @@ svg { .pending { .persona { - fill: var(--color-pending); display: block; + fill: var(--color-pending); } .check { @@ -97,8 +97,8 @@ svg { } .question-mark { - fill: var(--color-pending); display: block; + fill: var(--color-pending); } .reviewer-number { @@ -108,8 +108,8 @@ svg { .submitted { .persona { - fill: var(--color-primary); display: block; + fill: var(--color-primary); } .check { @@ -125,17 +125,17 @@ svg { } .reviewer-number { - font-family: 'Fira Sans Condensed'; - font-weight: 600; + fill: var(--color-primary); + font-family: 'Fira Sans Condensed', sans-serif; font-size: 50px; font-style: normal; + font-weight: 600; stroke: none; - fill: var(--color-primary); text-transform: uppercase; } } .fullname { - font-family: var(--font-reviewer); color: red; + font-family: var(--font-reviewer); } diff --git a/packages/xpub-ui/src/atoms/Badge.js b/packages/xpub-ui/src/atoms/Badge.js index d5ee2d540495389646254e2fec0a1e1d10768e6c..eb6f00420bc27789af4fc134841df0fd81c1ef54 100644 --- a/packages/xpub-ui/src/atoms/Badge.js +++ b/packages/xpub-ui/src/atoms/Badge.js @@ -4,7 +4,9 @@ import classes from './Badge.local.scss' const Badge = ({ count, label, plural }) => ( <span className={classes.root}> <span className={classes.count}>{count}</span> - <span className={classes.label}>{plural && count !== 1 ? plural : label}</span> + <span className={classes.label}> + {plural && count !== 1 ? plural : label} + </span> </span> ) diff --git a/packages/xpub-ui/src/atoms/Badge.local.scss b/packages/xpub-ui/src/atoms/Badge.local.scss index 440ad26b535077eac519ee4f91d66799ea51153b..b5eb36513d24d1164aa00e4eabec4cc6c5369c8d 100644 --- a/packages/xpub-ui/src/atoms/Badge.local.scss +++ b/packages/xpub-ui/src/atoms/Badge.local.scss @@ -1,21 +1,21 @@ .root { - display: inline-flex; align-items: center; - background: lightgrey; + // background: lightgrey; background: linear-gradient(#fff 0, #fff 1.1em, grey 1.1em, grey 1.15em, #fff 1.15em, #fff 2em); + color: inherit; + display: inline-flex; font-size: 0.8rem; margin-right: 1em; padding-bottom: 1em; - color: inherit; } .count { border-radius: 50%; - text-align: center; - font-weight: 600; color: grey; font-size: 1em; + font-weight: 600; padding-right: 0.5em; + text-align: center; } .label { diff --git a/packages/xpub-ui/src/atoms/Button.js b/packages/xpub-ui/src/atoms/Button.js index c15cb9a47710b95234f09a35b36d83f44c289948..3f8163badc80d4292438e582d3bebb7bd00f1ace 100644 --- a/packages/xpub-ui/src/atoms/Button.js +++ b/packages/xpub-ui/src/atoms/Button.js @@ -2,16 +2,25 @@ import React from 'react' import classnames from 'classnames' import classes from './Button.local.scss' -const Button = ({ className, children, type = 'button', disabled, primary, onClick}) => ( +const Button = ({ + className, + children, + type = 'button', + disabled, + primary, + onClick, +}) => ( <button className={classnames(className, classes.root, { [classes.disabled]: disabled, - [classes.primary]: primary + [classes.primary]: primary, })} - type={type} disabled={disabled} - onClick={onClick}>{children}</button> + onClick={onClick} + type={type} + > + {children} + </button> ) export default Button - diff --git a/packages/xpub-ui/src/atoms/Button.local.scss b/packages/xpub-ui/src/atoms/Button.local.scss index 8eaf7dca68de16f63713bded88980e27efe05720..75b469bc14603e396f885531617c2fd83e869c56 100644 --- a/packages/xpub-ui/src/atoms/Button.local.scss +++ b/packages/xpub-ui/src/atoms/Button.local.scss @@ -1,13 +1,13 @@ .root { - text-transform: uppercase; - font-family: var(--font-interface); - letter-spacing: 0.05em; + background: #ddd; border: none; + cursor: pointer; + font-family: var(--font-interface); font-size: inherit; + letter-spacing: 0.05em; padding: 10px 20px; position: relative; - background: #ddd; - cursor: pointer; + text-transform: uppercase; } .root:hover, @@ -34,31 +34,31 @@ } .root ::after { - opacity: 1; animation: 1s warning; + opacity: 1; } .primary { background-color: var(--color-primary); - color: white; border: 2px solid transparent; border-bottom: 4px solid var(--color-primary); + color: white; } .primary:hover { background: white; - color: var(--color-primary); border: 2px solid var(--color-primary); border-bottom: 4px solid var(--color-primary); + color: var(--color-primary); outline: 1px solid transparent; } .primary:focus { background: white; - color: var(--color-primary); border: 2px solid var(--color-primary); border-bottom: 4px solid var(--color-primary); box-shadow: 0 2px 0 0 var(--color-primary); + color: var(--color-primary); outline: 1px solid transparent; } @@ -70,34 +70,34 @@ } .disabled:hover { - cursor: not-allowed; background: transparent; - color: #aaa; border: 2px solid transparent; border-bottom: 2px solid #bbb; + color: #aaa; + cursor: not-allowed; } .disabled:hover::after { - text-transform: lowercase; - letter-spacing: 0; + color: var(--color-danger); content: "sorry, this action is not possible"; - position: absolute; display: inline; - top: 30%; - left: 115%; - font-style: italic; font-size: 0.9em; - color: var(--color-danger); - width: 30ch; - text-align: left; + font-style: italic; + left: 115%; + letter-spacing: 0; opacity: 1; + position: absolute; + text-align: left; + text-transform: lowercase; + top: 30%; + // width: 30ch; } .addFile { background: none; + border: none; font-style: normal; - text-transform: none; - padding: 0; letter-spacing: 0; - border: none; + padding: 0; + text-transform: none; } diff --git a/packages/xpub-ui/src/atoms/Checkbox.js b/packages/xpub-ui/src/atoms/Checkbox.js index 8dde21105feae9b353897c64821815a7f39ebf7b..987849bf2ccc01165d1b585750da116b0223fd08 100644 --- a/packages/xpub-ui/src/atoms/Checkbox.js +++ b/packages/xpub-ui/src/atoms/Checkbox.js @@ -2,18 +2,29 @@ import React from 'react' import classnames from 'classnames' import classes from './Checkbox.local.scss' -const Checkbox = ({ inline, name, value, label, checked, required, onChange }) => ( - <label className={classnames(classes.root, { - [classes.inline]: inline - })}> +const Checkbox = ({ + inline, + name, + value, + label, + checked, + required, + onChange, +}) => ( + <label + className={classnames(classes.root, { + [classes.inline]: inline, + })} + > <input + checked={checked || false} className={classes.input} - type="checkbox" name={name} - value={value} - checked={checked || false} + onChange={onChange} required={required} - onChange={onChange}/> + type="checkbox" + value={value} + /> <span>{label}</span> </label> ) diff --git a/packages/xpub-ui/src/atoms/Checkbox.local.scss b/packages/xpub-ui/src/atoms/Checkbox.local.scss index ffeafbca4b3086ecdbce97b351454f439f514df2..3c66c3b3a2ed0f1472126755f2e553b155a3ac39 100644 --- a/packages/xpub-ui/src/atoms/Checkbox.local.scss +++ b/packages/xpub-ui/src/atoms/Checkbox.local.scss @@ -1,11 +1,11 @@ .root { - display: flex; align-items: center; - transition: all 2s; - font-size: 1em; + display: flex; font-family: var(--font-author); + font-size: 1em; font-style: italic; letter-spacing: 1px; + transition: all 2s; } .root.inline { @@ -21,20 +21,20 @@ } .root .input { - margin-right: 0.25rem; display: none; + margin-right: 0.25rem; } .root span::before { - transition: border 0.5s ease, background-size 0.3s ease; + background-size: 0; + border: 1px solid black; // border-radius: 20px; content: ' '; display: inline-block; - vertical-align: middle; - width: 9px; height: 9px; - border: 1px solid black; // border-radius: 20px; - background-size: 0; margin-right: 0.3em; + transition: border 0.5s ease, background-size 0.3s ease; + vertical-align: middle; + width: 9px; } .root:hover span::before { @@ -47,10 +47,10 @@ font-weight: 600; &::before { - transition: border 0.5s ease, background-size 0.3s ease; - border: 1px solid black; background: black; + border: 1px solid black; box-shadow: inset 1px 1px 0 0 white, inset -1px -1px 0 0 white; + transition: border 0.5s ease, background-size 0.3s ease; } } diff --git a/packages/xpub-ui/src/atoms/File.js b/packages/xpub-ui/src/atoms/File.js index 4eca93ba0063d5827a56c45719243b6567e95606..93e5ef6d12136c7b25db379dc6c1d24fd32a3637 100644 --- a/packages/xpub-ui/src/atoms/File.js +++ b/packages/xpub-ui/src/atoms/File.js @@ -6,13 +6,11 @@ const extension = ({ name }) => name.replace(/^.+\./, '') const File = ({ value }) => ( <div className={classes.root}> <div className={classes.icon}> - <div className={classes.extension}> - {extension(value)} - </div> + <div className={classes.extension}>{extension(value)}</div> </div> <div className={classes.name}> - <a href={value.url} download={value.name}> + <a download={value.name} href={value.url}> {value.name} </a> </div> diff --git a/packages/xpub-ui/src/atoms/File.local.scss b/packages/xpub-ui/src/atoms/File.local.scss index 7877da0c068645b3b243302db23eaf945fb32cff..b751734209305fadec52e1127df5c48d4ae7f83c 100644 --- a/packages/xpub-ui/src/atoms/File.local.scss +++ b/packages/xpub-ui/src/atoms/File.local.scss @@ -1,93 +1,91 @@ .root { + align-items: center; display: inline-flex; flex-direction: column; - align-items: center; - position: relative; margin-bottom: 2em; margin-right: 3em; + position: relative; width: 20ch; &::before, &::after { - transition: transform 0.3s; cursor: pointer; + transition: transform 0.3s; } &::after { - content: 'remove'; background: var(--color-danger); + border: 1px solid white; color: white; - position: absolute; + content: 'remove'; + cursor: pointer; + font-size: 0.8em; left: 70%; + letter-spacing: 0.5px; + padding: 0.2em 0.4em; + position: absolute; + text-transform: uppercase; top: 4em; transform: scaleX(0); transform-origin: 0 0; - font-size: 0.8em; - padding: 0.2em 0.4em; - letter-spacing: 0.5px; - text-transform: uppercase; z-index: 2; - cursor: pointer; - border: 1px solid white; } &::before { - content: 'replace'; background: var(--color-primary); + border: 1px solid white; color: white; - position: absolute; - left: 70%; - top: 6em; - transform-origin: 0 0; + content: 'replace'; cursor: pointer; - transform: scaleX(0); font-size: 0.8em; + left: 70%; + letter-spacing: 0.5px; padding: 0.2em 0.4em; + position: absolute; text-transform: uppercase; - letter-spacing: 0.5px; + top: 6em; + transform: scaleX(0); + transform-origin: 0 0; z-index: 3; - border: 1px solid white; } .icon { - transition: transform 0.3s ease; - width: 70px; - height: 100px; background: #ddd; - position: relative; + height: 100px; padding: 5px; + position: relative; + transition: transform 0.3s ease; + width: 70px; } .extension { - position: absolute; - top: 20px; - right: 0; - left: 20px; - text-align: center; - text-transform: uppercase; background: #888; color: white; font-size: 12px; + left: 20px; padding: 2px; + position: absolute; + right: 0; + text-align: center; + text-transform: uppercase; + top: 20px; } .name { - font-style: italic; - font-size: 0.9em; color: #aaa; + font-size: 0.9em; + font-style: italic; margin: 5px; max-width: 15ch; - - /* to divide into lines */ - word-break: break-all; text-align: center; + word-break: break-all; /* to divide into lines */ } &:hover { .extension { background: white; - color: var(--color-primary); border-right: 2px solid #ddd; + color: var(--color-primary); } .icon { diff --git a/packages/xpub-ui/src/atoms/Icon.js b/packages/xpub-ui/src/atoms/Icon.js index 672dd89160f75034e09f31ed24755842f1bcd6b2..26a904615c5d9d4477665a7fe0b268d440657177 100644 --- a/packages/xpub-ui/src/atoms/Icon.js +++ b/packages/xpub-ui/src/atoms/Icon.js @@ -10,9 +10,7 @@ const Icon = ({ children, color = 'black', size = 24 }) => { // select the icon const icon = icons[name] - return ( - <span className={classes.root}>{icon({ color, size })}</span> - ) + return <span className={classes.root}>{icon({ color, size })}</span> } export default Icon diff --git a/packages/xpub-ui/src/atoms/Menu.js b/packages/xpub-ui/src/atoms/Menu.js index 3029ee3e20eefdacf327e293a0f49f3e2a188377..e1e23a051b40c41c37b6c5da0dd3991f39f1ed39 100644 --- a/packages/xpub-ui/src/atoms/Menu.js +++ b/packages/xpub-ui/src/atoms/Menu.js @@ -6,25 +6,25 @@ import classes from './Menu.local.scss' // TODO: use a <select> element instead of divs? class Menu extends React.Component { - constructor (props) { + constructor(props) { super(props) this.state = { open: false, - selected: props.value + selected: props.value, } } toggleMenu = () => { this.setState({ - open: !this.state.open + open: !this.state.open, }) } handleSelect = selected => { this.setState({ + open: false, selected, - open: false }) this.props.onChange(selected) @@ -36,24 +36,25 @@ class Menu extends React.Component { return options.find(option => option.value === value).label } - render () { + render() { const { label, options, placeholder = 'Choose in the list' } = this.props const { open, selected } = this.state return ( - <div className={classnames(classes.root, { - [classes.open]: open - })}> - {label && ( - <span className={classes.label}>{label}</span> - )} + <div + className={classnames(classes.root, { + [classes.open]: open, + })} + > + {label && <span className={classes.label}>{label}</span>} <div className={classes.main}> <div className={classes.openerContainer}> <button - type="button" className={classes.opener} - onClick={this.toggleMenu}> + onClick={this.toggleMenu} + type="button" + > {selected ? ( <span>{this.optionLabel(selected)}</span> ) : ( @@ -68,12 +69,14 @@ class Menu extends React.Component { <div className={classes.options}> {options.map(option => ( <div - key={option.value} className={classnames(classes.option, { - [classes.active]: option.value === selected + [classes.active]: option.value === selected, })} + key={option.value} onClick={() => this.handleSelect(option.value)} - >{option.label || option.value}</div> + > + {option.label || option.value} + </div> ))} </div> )} diff --git a/packages/xpub-ui/src/atoms/Menu.local.scss b/packages/xpub-ui/src/atoms/Menu.local.scss index ad15e56771be0cdb1dec7a867cb13a64c6007050..67555549e2164db6720decd22af548b8411ac0cf 100644 --- a/packages/xpub-ui/src/atoms/Menu.local.scss +++ b/packages/xpub-ui/src/atoms/Menu.local.scss @@ -1,6 +1,6 @@ .root { - display: flex; align-items: center; + display: flex; } .label { @@ -16,15 +16,15 @@ } .opener { + align-items: center; + background: transparent; border: none; - outline: none; + border-left: 2px solid transparent; cursor: pointer; - background: transparent; - font-size: inherit; - font-family: var(--font-author); display: flex; - align-items: center; - border-left: 2px solid transparent; + font-family: var(--font-author); + font-size: inherit; + outline: none; } .opener:hover { @@ -32,8 +32,8 @@ } .open .opener { - color: var(--color-primary); border-left: 2px solid var(--color-primary); + color: var(--color-primary); } .placeholder { @@ -47,8 +47,8 @@ } .arrow { - margin-left: 10px; font-size: 50%; + margin-left: 10px; transform: scaleY(1.2) scaleX(2.2); transition: transform 0.2s; } @@ -58,16 +58,16 @@ } .options { - position: absolute; - padding-top: 0.5em; - top: 0; - left: 0; - min-width: 10em; background-color: white; - border-left: 2px solid var(--color-primary); border-bottom: 2px solid var(--color-primary); + border-left: 2px solid var(--color-primary); // columns: 2 auto; + left: 0; + min-width: 10em; opacity: 0; + padding-top: 0.5em; + position: absolute; + top: 0; z-index: 10; } @@ -76,8 +76,8 @@ } .option { - font-family: var(--font-author); cursor: pointer; + font-family: var(--font-author); padding: 10px; white-space: nowrap; } @@ -87,7 +87,6 @@ } .active { - // placeholder for the semibold - font-weight: 600; color: black; + font-weight: 600; /* placeholder for the semibold */ } diff --git a/packages/xpub-ui/src/atoms/Radio.js b/packages/xpub-ui/src/atoms/Radio.js index 48e34fddd5416f87a9c8fb539b33807761e3af1f..04c6b6df95aaf55f94a2a54bb729da81903aa685 100644 --- a/packages/xpub-ui/src/atoms/Radio.js +++ b/packages/xpub-ui/src/atoms/Radio.js @@ -2,24 +2,48 @@ import React from 'react' import classnames from 'classnames' import classes from './Radio.local.scss' -const inputGradient = color => `radial-gradient(closest-corner at center, ${color} 0%, ${color} 45%, white 45%, white 100%)` +const inputGradient = color => + `radial-gradient(closest-corner at center, ${color} 0%, ${ + color + } 45%, white 45%, white 100%)` -const Radio = ({ className, color = 'black', inline, name, value, label, checked, required, onChange }) => ( - <label className={classnames(classes.root, { - [classes.inline]: inline, - [classes.checked]: checked - }, className)} style={{color}}> +const Radio = ({ + className, + color = 'black', + inline, + name, + value, + label, + checked, + required, + onChange, +}) => ( + <label + className={classnames( + classes.root, + { + [classes.inline]: inline, + [classes.checked]: checked, + }, + className, + )} + style={{ color }} + > <input + checked={checked} className={classes.input} - type="radio" name={name} - value={value} - checked={checked} + onChange={onChange} required={required} - onChange={onChange}/> + type="radio" + value={value} + /> <span className={classes.pseudoInput} - style={{ background: checked ? inputGradient(color) : 'transparent' }}> </span> + style={{ background: checked ? inputGradient(color) : 'transparent' }} + > + {' '} + </span> <span className={classes.label}>{label}</span> </label> ) diff --git a/packages/xpub-ui/src/atoms/Radio.local.scss b/packages/xpub-ui/src/atoms/Radio.local.scss index ec5b0b867c1c3c71344174db25992b00b1b758be..49f699cb136a177a36311a8d45eba9118c982e38 100644 --- a/packages/xpub-ui/src/atoms/Radio.local.scss +++ b/packages/xpub-ui/src/atoms/Radio.local.scss @@ -1,7 +1,7 @@ .root { - display: flex; align-items: center; cursor: pointer; + display: flex; transition: all 2s; } @@ -20,10 +20,10 @@ /* label text */ .label { - font-size: 1em; + display: inline-block; font-family: inherit; + font-size: 1em; font-style: italic; - display: inline-block; letter-spacing: 1px; } @@ -40,17 +40,17 @@ /* pseudo-input */ .pseudoInput { - transition: border 0.5s ease, background-size 0.3s ease; + background-size: 0; + border-color: transparent; + border-radius: 10px; + box-shadow: 0 0 0 1px; content: " "; display: inline-block; - vertical-align: center; - width: 10px; height: 10px; - border-color: transparent; - box-shadow: 0 0 0 1px; - border-radius: 10px; - background-size: 0; margin-right: 0.3em; + transition: border 0.5s ease, background-size 0.3s ease; + vertical-align: center; + width: 10px; } .root:not(.checked):hover .pseudoInput { diff --git a/packages/xpub-ui/src/atoms/Tags.js b/packages/xpub-ui/src/atoms/Tags.js index 63fe2c53cce7bc247ae9de6bac07b6f0ddea71ad..c16f599471e153782d0baaba22f6b4cc8e2af537 100644 --- a/packages/xpub-ui/src/atoms/Tags.js +++ b/packages/xpub-ui/src/atoms/Tags.js @@ -6,11 +6,11 @@ import './Tags.scss' // TODO: allow tags to be edited class Tags extends React.Component { - constructor (props) { + constructor(props) { super(props) this.state = { - tags: props.value || [] + tags: props.value || [], } } @@ -34,23 +34,24 @@ class Tags extends React.Component { this.props.onChange(tags) } - render () { + render() { const { tags } = this.state const { name, suggestions, placeholder } = this.props return ( <ReactTags - name={name} - tags={tags} - suggestions={suggestions} - placeholder={placeholder} + allowNew autofocus={false} - allowNew={true} // TODO: enable these when react-tag-autocomplete update is released // delimiters={[]} // delimiterChars={[',', ';']} + handleAddition={this.handleAddition} handleDelete={this.handleDelete} - handleAddition={this.handleAddition}/> + name={name} + placeholder={placeholder} + suggestions={suggestions} + tags={tags} + /> ) } } diff --git a/packages/xpub-ui/src/atoms/TextField.js b/packages/xpub-ui/src/atoms/TextField.js index 4b4b8f94a913bf5106226a43cb453db55fe30da7..443c52b5c2c74efcec233a5d5554fcc307f54946 100644 --- a/packages/xpub-ui/src/atoms/TextField.js +++ b/packages/xpub-ui/src/atoms/TextField.js @@ -1,18 +1,28 @@ import React from 'react' import classes from './TextField.local.scss' -const TextField = ({ label, name, placeholder, required, type = 'text', value = '', onBlur, onChange }) => ( +const TextField = ({ + label, + name, + placeholder, + required, + type = 'text', + value = '', + onBlur, + onChange, +}) => ( <label className={classes.root}> {label && <span className={classes.text}>{label}</span>} <input className={classes.input} name={name} - type={type} - value={value} + onBlur={onBlur} + onChange={onChange} placeholder={placeholder} required={required} - onBlur={onBlur} - onChange={onChange}/> + type={type} + value={value} + /> </label> ) diff --git a/packages/xpub-ui/src/atoms/TextField.local.scss b/packages/xpub-ui/src/atoms/TextField.local.scss index 7c2767c7cb6af897024329054f2664f2237674d1..b857af22d142c3148eb332d2017759bb0575ad3f 100644 --- a/packages/xpub-ui/src/atoms/TextField.local.scss +++ b/packages/xpub-ui/src/atoms/TextField.local.scss @@ -1,6 +1,6 @@ .root { - display: flex; align-items: center; + display: flex; } .text { @@ -15,21 +15,21 @@ .root input { border: 0 none; - padding: 0; border-bottom: 1px dashed #aaa; font-family: "Vollkorn", serif; + padding: 0; &:hover, &:focus { - outline-style: none; - box-shadow: none; - border-color: transparent; border-bottom: 1px dashed var(--color-primary); + border-color: transparent; + box-shadow: none; + outline-style: none; } } .root input::placeholder { - font-style: italic; - font-family: var(--font-interface); color: #777; + font-family: var(--font-interface); + font-style: italic; } diff --git a/packages/xpub-ui/src/atoms/UploadingFile.js b/packages/xpub-ui/src/atoms/UploadingFile.js index ecb3a865608797b9f52fdfff04701e0ccd618102..b5f6b6ad6ec878e14af98a0760cdbb81a0b3b28e 100644 --- a/packages/xpub-ui/src/atoms/UploadingFile.js +++ b/packages/xpub-ui/src/atoms/UploadingFile.js @@ -7,22 +7,17 @@ const extension = ({ name }) => name.replace(/^.+\./, '') const UploadingFile = ({ file, error, progress }) => ( <div className={classes.root}> - {!!error && ( - <div className={classes.error}> - {error} - </div> - )} + {!!error && <div className={classes.error}>{error}</div>} <div className={classes.icon}> {!!progress && ( <div className={classes.progress} - style={{ top: (progress * 100) + '%' }}/> + style={{ top: `${progress * 100}%` }} + /> )} - <div className={classes.extension}> - {extension(file)} - </div> + <div className={classes.extension}>{extension(file)}</div> </div> <div className={classes.name}>{file.name}</div> diff --git a/packages/xpub-ui/src/atoms/UploadingFile.local.scss b/packages/xpub-ui/src/atoms/UploadingFile.local.scss index 5eef06958b86a0ec005ece48aaa6c0e6c89b6b32..895148f991ee7a40d95a9b28975b0510ed529111 100644 --- a/packages/xpub-ui/src/atoms/UploadingFile.local.scss +++ b/packages/xpub-ui/src/atoms/UploadingFile.local.scss @@ -1,79 +1,79 @@ .root { + align-items: center; display: inline-flex; flex-direction: column; - align-items: center; - position: relative; margin-bottom: 2em; margin-right: 3em; + position: relative; width: 20ch; } .icon { - opacity: 0.5; - width: 70px; - height: 100px; background: #ddd; - position: relative; + height: 100px; margin: 5px; + opacity: 0.5; + position: relative; + width: 70px; } .progress { - opacity: 1; - position: absolute; - bottom: 0; - right: 0; - left: 0; - content: ''; - display: block; - transform-origin: 0 0; background-image: linear-gradient( - to top, var(--color-primary-light) 50%, - var(--color-primary) 75% + var(--color-primary) 75%, + to top ); + bottom: 0; + content: ''; + display: block; + left: 0; + opacity: 1; + position: absolute; + right: 0; + transform-origin: 0 0; &::after { /* we can use a data attribute for the numbering below */ + bottom: 2px; + color: white; content: "00%"; display: block; - color: white; position: absolute; - bottom: 2px; right: 2px; } } .error { - font-size: 0.8em; - letter-spacing: 0.01em; background: var(--color-danger); border: 2px solid white; color: white; + font-size: 0.8em; + letter-spacing: 0.01em; opacity: 1; + padding: 0.3em 0.5em; position: absolute; top: 25%; z-index: 4; - padding: 0.3em 0.5em; } .extension { - position: absolute; - top: 20px; - right: 0; - left: 20px; - text-align: center; - text-transform: uppercase; background: #888; color: white; font-size: 12px; + left: 20px; padding: 2px; + position: absolute; + right: 0; + text-align: center; + text-transform: uppercase; + top: 20px; } .name { - font-style: italic; - font-size: 90%; color: gray; + font-size: 90%; + font-style: italic; margin: 5px; max-width: 20ch; } diff --git a/packages/xpub-ui/src/atoms/ValidatedField.js b/packages/xpub-ui/src/atoms/ValidatedField.js index c878ac5c94bdd93bbf785b5f48b341416f313619..379accfcf98dbe0dbf5613f9bf08deadcdb4b875 100644 --- a/packages/xpub-ui/src/atoms/ValidatedField.js +++ b/packages/xpub-ui/src/atoms/ValidatedField.js @@ -10,30 +10,31 @@ const ValidatedFieldComponent = ({ component }) => ({ meta, input }) => ( <div> {component(input)} - {meta.touched && (meta.error || meta.warning) && ( - <div className={classes.messages}> - {meta.error && ( - <div className={classnames(classes.message, classes.error)}> - {meta.error} - </div> - )} + {meta.touched && + (meta.error || meta.warning) && ( + <div className={classes.messages}> + {meta.error && ( + <div className={classnames(classes.message, classes.error)}> + {meta.error} + </div> + )} - {meta.warning && ( - <div className={classnames(classes.message, classes.warning)}> - {meta.warning} - </div> - )} - </div> - )} + {meta.warning && ( + <div className={classnames(classes.message, classes.warning)}> + {meta.warning} + </div> + )} + </div> + )} </div> ) const ValidatedField = ({ fieldComponent, ...rest }) => ( - <Field {...rest} component={fieldComponent}/> + <Field {...rest} component={fieldComponent} /> ) export default compose( withHandlers({ - fieldComponent: ValidatedFieldComponent - }) + fieldComponent: ValidatedFieldComponent, + }), )(ValidatedField) diff --git a/packages/xpub-ui/src/atoms/ValidatedField.local.scss b/packages/xpub-ui/src/atoms/ValidatedField.local.scss index ea641fa6c3c7717beaf9dd634c53dc4ef25d0740..3ba44df3b8f9ad4dc2fabec0743c8b7040960b3b 100644 --- a/packages/xpub-ui/src/atoms/ValidatedField.local.scss +++ b/packages/xpub-ui/src/atoms/ValidatedField.local.scss @@ -3,10 +3,10 @@ } .messages { - margin-top: 10px; - font-style: italic; display: inline-block; + font-style: italic; margin-left: 1em; + margin-top: 10px; } .message:not(:last-child) { diff --git a/packages/xpub-ui/src/molecules/AppBar.js b/packages/xpub-ui/src/molecules/AppBar.js index 4af63917e70389548e029c0d42166b5329bdbf30..c1d562ab9abcd18a0dd2a1ee241360ffd30b6790 100644 --- a/packages/xpub-ui/src/molecules/AppBar.js +++ b/packages/xpub-ui/src/molecules/AppBar.js @@ -6,8 +6,12 @@ import Icon from '../atoms/Icon' const AppBar = ({ brandLink, brandName, loginLink, logoutLink, userName }) => ( <div className={classes.root}> - <Link to={brandLink || '/'} - className={classnames(classes.link, classes.logo)}>{brandName}</Link> + <Link + className={classnames(classes.link, classes.logo)} + to={brandLink || '/'} + > + {brandName} + </Link> <div> {userName && ( @@ -18,11 +22,16 @@ const AppBar = ({ brandLink, brandName, loginLink, logoutLink, userName }) => ( )} {userName ? ( - <Link to={logoutLink} - className={classnames(classes.item, classes.link)}>logout</Link> + <Link + className={classnames(classes.item, classes.link)} + to={logoutLink} + > + logout + </Link> ) : ( - <Link to={loginLink} - className={classnames(classes.item, classes.link)}>login</Link> + <Link className={classnames(classes.item, classes.link)} to={loginLink}> + login + </Link> )} </div> </div> diff --git a/packages/xpub-ui/src/molecules/AppBar.local.scss b/packages/xpub-ui/src/molecules/AppBar.local.scss index 99502973729000627b8ff6d6553836af9d9c76a4..da3ccddf37c158b54a1514e39d85019e163fd9e4 100644 --- a/packages/xpub-ui/src/molecules/AppBar.local.scss +++ b/packages/xpub-ui/src/molecules/AppBar.local.scss @@ -7,17 +7,17 @@ color: var(--color-primary); &::before { - text-align: center; color: #aaa; - height: 1em; display: inline-block; + height: 1em; margin-right: 0.3em; + text-align: center; } } .link:hover { - text-decoration: underline; cursor: pointer; + text-decoration: underline; &::before { color: var(--color-primary); @@ -25,9 +25,9 @@ } .item { - padding: 0 1rem; - display: inline-flex; align-items: center; + display: inline-flex; + padding: 0 1rem; } .username { diff --git a/packages/xpub-ui/src/molecules/Attachments.js b/packages/xpub-ui/src/molecules/Attachments.js index 6cf132182cd655c4b0d3d9e38d828347921b8755..c05eb487934d3afd84eb781165042e96655e562e 100644 --- a/packages/xpub-ui/src/molecules/Attachments.js +++ b/packages/xpub-ui/src/molecules/Attachments.js @@ -10,19 +10,15 @@ const Attachments = props => ( <Files {...props} buttonText="Attach file" + uploadedFile={value => <Attachment key={value.url} value={value} />} uploadingFile={({ file, progress, error }) => ( <div className={classes.uploading}> <span className={classes.icon}> <Icon color="var(--color-primary)">paperclip</Icon> </span> - <span className={classes.filename}> - {error ? error : 'Uploading…'} - </span> + <span className={classes.filename}>{error || 'Uploading…'}</span> </div> )} - uploadedFile={value => ( - <Attachment key={value.url} value={value}/> - )} /> ) diff --git a/packages/xpub-ui/src/molecules/Attachments.local.scss b/packages/xpub-ui/src/molecules/Attachments.local.scss index 49bf286103c840a195a093bd43bb386a62385bfa..67c036fe4dcea0013b463abcf34e2e5442dea10c 100644 --- a/packages/xpub-ui/src/molecules/Attachments.local.scss +++ b/packages/xpub-ui/src/molecules/Attachments.local.scss @@ -1,6 +1,6 @@ .uploading { - display: flex; align-items: center; + display: flex; } .icon { diff --git a/packages/xpub-ui/src/molecules/CheckboxGroup.js b/packages/xpub-ui/src/molecules/CheckboxGroup.js index 8874941661f4f3a47efbb429c25924eecbe3a51f..152bf26ce5e01870b61d93588c33245c92dcf4d7 100644 --- a/packages/xpub-ui/src/molecules/CheckboxGroup.js +++ b/packages/xpub-ui/src/molecules/CheckboxGroup.js @@ -2,18 +2,18 @@ import React from 'react' import Checkbox from '../atoms/Checkbox' class CheckboxGroup extends React.Component { - constructor (props) { + constructor(props) { super(props) this.state = { - values: props.value || [] + values: props.value || [], } } handleChange = event => { const { values } = this.state - const value = event.target.value + const { value } = event.target if (event.target.checked) { values.push(value) @@ -26,7 +26,7 @@ class CheckboxGroup extends React.Component { this.props.onChange(values) } - render () { + render() { const { inline, name, options, required } = this.props const { values } = this.state @@ -34,14 +34,15 @@ class CheckboxGroup extends React.Component { <div> {options.map(option => ( <Checkbox + checked={values.includes(option.value)} + inline={inline} key={option.value} + label={option.label} name={name} + onChange={this.handleChange} required={required} - inline={inline} value={option.value} - label={option.label} - checked={values.includes(option.value)} - onChange={this.handleChange}/> + /> ))} </div> ) diff --git a/packages/xpub-ui/src/molecules/Files.js b/packages/xpub-ui/src/molecules/Files.js index 329119ae8d5ef8dabbad56e6cbded57cc62dab18..d5d52d1b47c2205fdecca3cd3f3712d3e4a4574a 100644 --- a/packages/xpub-ui/src/molecules/Files.js +++ b/packages/xpub-ui/src/molecules/Files.js @@ -3,12 +3,12 @@ import classes from './Files.local.scss' import Upload from './Upload' class Files extends React.Component { - constructor (props) { + constructor(props) { super(props) this.state = { values: props.value || [], - uploads: [] + uploads: [], } } @@ -22,7 +22,7 @@ class Files extends React.Component { Array.from(event.target.files).forEach(file => { uploads.push({ file, - request: this.props.uploadFile(file) + request: this.props.uploadFile(file), }) }) @@ -32,19 +32,19 @@ class Files extends React.Component { handleUploadedFile = ({ file, url }) => { const values = this.state.values.concat({ name: file.name, - url + url, }) - const uploads = this.state.uploads.filter(item => { - return item.file.name !== file.name - }) + const uploads = this.state.uploads.filter( + item => item.file.name !== file.name, + ) this.setState({ values, uploads }) this.props.onChange(values) } - render () { + render() { const { name, buttonText, uploadingFile, uploadedFile } = this.props const { values, uploads } = this.state @@ -52,31 +52,34 @@ class Files extends React.Component { <div className={classes.root}> <div className={classes.upload}> <button - type="button" className={classes.attach} - onClick={() => this.fileInput.click()}> + onClick={() => this.fileInput.click()} + type="button" + > {buttonText} </button> <input className={classes.input} + multiple + name={name} + onChange={this.handleChange} ref={input => (this.fileInput = input)} type="file" - name={name} - multiple - onChange={this.handleChange}/> + /> </div> <div className={classes.files}> - {uploads && uploads.map(upload => ( - <Upload - key={upload.file.name} - file={upload.file} - request={upload.request} - handleUploadedFile={this.handleUploadedFile} - render={uploadingFile} - /> - ))} + {uploads && + uploads.map(upload => ( + <Upload + file={upload.file} + handleUploadedFile={this.handleUploadedFile} + key={upload.file.name} + render={uploadingFile} + request={upload.request} + /> + ))} {values && values.map(uploadedFile)} </div> diff --git a/packages/xpub-ui/src/molecules/Files.local.scss b/packages/xpub-ui/src/molecules/Files.local.scss index da6e025ebc32a66e6c55c90efd80cdfff27a7083..b6e58a85f85b3148688af89b7f95a724b630b35b 100644 --- a/packages/xpub-ui/src/molecules/Files.local.scss +++ b/packages/xpub-ui/src/molecules/Files.local.scss @@ -3,32 +3,32 @@ } .button { - border: 1px dashed grey; background: transparent; - padding: 10px; + border: 1px dashed grey; cursor: pointer; - font-size: inherit; font-family: inherit; + font-size: inherit; margin-bottom: 2em; + padding: 10px; } .button:hover { - color: var(--color-primary); border-color: var(--color-primary); + color: var(--color-primary); } .files { + font-size: 0.9em; font-style: italic; line-height: 1.5; - font-size: 0.9em; } .attach { - border: 1px dashed grey; background: transparent; - padding: 10px; + border: 1px dashed grey; cursor: pointer; - font-size: inherit; font-family: inherit; + font-size: inherit; margin-bottom: 2em; + padding: 10px; } diff --git a/packages/xpub-ui/src/molecules/PlainButton.js b/packages/xpub-ui/src/molecules/PlainButton.js index 741e65c02a928e7c7a32eca4e6eea93d6f2b84db..dc71790905fe3b0defa827ba2580c5795a096deb 100644 --- a/packages/xpub-ui/src/molecules/PlainButton.js +++ b/packages/xpub-ui/src/molecules/PlainButton.js @@ -3,14 +3,23 @@ import classnames from 'classnames' import Button from '../atoms/Button' import classes from './PlainButton.local.scss' -const PlainButton = ({ className, children, type, disabled, primary, onClick }) => ( +const PlainButton = ({ + className, + children, + type, + disabled, + primary, + onClick, +}) => ( <Button className={classnames(classes.root, className)} - type={type} - primary={primary} disabled={disabled} - onClick={onClick}>{children}</Button> + onClick={onClick} + primary={primary} + type={type} + > + {children} + </Button> ) export default PlainButton - diff --git a/packages/xpub-ui/src/molecules/PlainButton.local.scss b/packages/xpub-ui/src/molecules/PlainButton.local.scss index 522d12ce6f5238e7aabf636f363bc4a8a7a901df..2b196748161d96f86cfa06052ace9ef19932740e 100644 --- a/packages/xpub-ui/src/molecules/PlainButton.local.scss +++ b/packages/xpub-ui/src/molecules/PlainButton.local.scss @@ -1,17 +1,17 @@ .root.root { background: none; - font-style: italic; - text-transform: none; - padding: 0; - letter-spacing: 0; border: 0; border-bottom: 2px solid #777; + font-style: italic; + letter-spacing: 0; + padding: 0; + text-transform: none; } .root.root:hover, .root.root:focus { - border: 0; background: transparent; + border: 0; border-bottom: 2px solid var(--color-primary); color: var(--color-primary); } diff --git a/packages/xpub-ui/src/molecules/RadioGroup.js b/packages/xpub-ui/src/molecules/RadioGroup.js index a6a5eb6f3ac6c1174a426174ee7a6d2be5a9a1f9..75b2f4f65659459c7f9ef642514d4c3140eaf74e 100644 --- a/packages/xpub-ui/src/molecules/RadioGroup.js +++ b/packages/xpub-ui/src/molecules/RadioGroup.js @@ -2,23 +2,21 @@ import React from 'react' import Radio from '../atoms/Radio' class RadioGroup extends React.Component { - constructor (props) { + constructor(props) { super(props) this.state = { - value: props.value + value: props.value, } } handleChange = event => { - const value = event.target.value - + const { value } = event.target this.setState({ value }) - this.props.onChange(value) } - render () { + render() { const { inline, name, options, required } = this.props const { value } = this.state @@ -26,15 +24,16 @@ class RadioGroup extends React.Component { <div> {options.map(option => ( <Radio + checked={option.value === value} + color={option.color} + inline={inline} key={option.value} + label={option.label} name={name} + onChange={this.handleChange} required={required} - inline={inline} value={option.value} - label={option.label} - color={option.color} - checked={option.value === value} - onChange={this.handleChange}/> + /> ))} </div> ) diff --git a/packages/xpub-ui/src/molecules/Supplementary.js b/packages/xpub-ui/src/molecules/Supplementary.js index 6a20b5aafc681899b37850f17bcb7647f929de51..b876ff92e2202bae6aa5f51dedfa53e2b600edc7 100644 --- a/packages/xpub-ui/src/molecules/Supplementary.js +++ b/packages/xpub-ui/src/molecules/Supplementary.js @@ -7,18 +7,16 @@ const Supplementary = props => ( <Files {...props} buttonText="↑ Upload files" + uploadedFile={value => <File key={value.url} value={value} />} uploadingFile={({ file, progress, error }) => ( <UploadingFile - key={file.name} + error={error} file={file} + key={file.name} progress={progress} - error={error}/> + /> )} - uploadedFile={value => ( - <File - key={value.url} - value={value}/> - )}/> + /> ) export default Supplementary diff --git a/packages/xpub-ui/src/molecules/Upload.js b/packages/xpub-ui/src/molecules/Upload.js index 8241fa4038f5286da249b9fa2d7288e6878de951..cb1e244bade4c5619baebc3e60e18cc073fc372d 100644 --- a/packages/xpub-ui/src/molecules/Upload.js +++ b/packages/xpub-ui/src/molecules/Upload.js @@ -5,11 +5,11 @@ import React from 'react' class Upload extends React.Component { state = { - progress: 0, error: undefined, + progress: 0, } - componentDidMount () { + componentDidMount() { const { request } = this.props request.addEventListener('progress', this.handleProgress) @@ -23,40 +23,40 @@ class Upload extends React.Component { if (!event.lengthComputable) return this.setState({ - progress: event.loaded / event.total + progress: event.loaded / event.total, }) } handleLoad = event => { if (this.props.request.status === 200) { this.setState({ - progress: 1 + progress: 1, }) this.props.handleUploadedFile({ file: this.props.file, - url: this.props.request.responseText + url: this.props.request.responseText, }) } else { this.setState({ - error: 'There was an error' + error: 'There was an error', }) } } handleError = event => { this.setState({ - error: 'There was an error' + error: 'There was an error', }) } handleAbort = event => { this.setState({ - error: 'The upload was cancelled' + error: 'The upload was cancelled', }) } - render () { + render() { const { file, render } = this.props const { progress, error } = this.state diff --git a/packages/xpub-ui/src/molecules/YesOrNo.js b/packages/xpub-ui/src/molecules/YesOrNo.js index 1d16de39d3910f7f9f311eb68124fe044cd630e7..31cac4ddde4d536dfa59e556a50e60bc57bc53e4 100644 --- a/packages/xpub-ui/src/molecules/YesOrNo.js +++ b/packages/xpub-ui/src/molecules/YesOrNo.js @@ -4,24 +4,25 @@ import classes from './YesOrNo.local.scss' const options = [ { + label: 'Yes', value: 'yes', - label: 'Yes' }, { + label: 'No', value: 'no', - label: 'No' - } + }, ] const YesOrNo = ({ name, value, required, onChange }) => ( <RadioGroup className={classes.root} + inline name={name} + onChange={onChange} options={options} - value={value} required={required} - inline={true} - onChange={onChange}/> + value={value} + /> ) export default YesOrNo diff --git a/packages/xpub-ui/styleguide.config.js b/packages/xpub-ui/styleguide.config.js index 18efe3b1dd8b1856882cd945a5d694b4748aa527..8b14c4584ffe5d7db00e06d7fcfc6fa4042ffe97 100644 --- a/packages/xpub-ui/styleguide.config.js +++ b/packages/xpub-ui/styleguide.config.js @@ -1,37 +1,39 @@ module.exports = { - title: 'xpub-ui style guide', - styleguideComponents: { - StyleGuideRenderer: require.resolve('xpub-styleguide/src/components/StyleGuideRenderer'), - Wrapper: require.resolve('xpub-styleguide/src/components/Wrapper') - }, context: { faker: 'faker', }, - skipComponentsWithoutExample: true, - theme: { - fontFamily: { - base: '"Fira Sans", sans-serif' - }, - color: { - link: 'cornflowerblue' - } - }, sections: [ { + content: 'docs/colors.md', name: 'Colors', - content: 'docs/colors.md' }, { + content: 'docs/fonts.md', name: 'Fonts', - content: 'docs/fonts.md' }, { + components: 'src/atoms/*.js', name: 'Atoms', - components: 'src/atoms/*.js' }, { + components: 'src/molecules/*.js', name: 'Molecules', - components: 'src/molecules/*.js' - } - ] + }, + ], + skipComponentsWithoutExample: true, + styleguideComponents: { + StyleGuideRenderer: require.resolve( + 'xpub-styleguide/src/components/StyleGuideRenderer', + ), + Wrapper: require.resolve('xpub-styleguide/src/components/Wrapper'), + }, + theme: { + color: { + link: 'cornflowerblue', + }, + fontFamily: { + base: '"Fira Sans", sans-serif', + }, + }, + title: 'xpub-ui style guide', } diff --git a/packages/xpub-ui/test/AppBar.test.js b/packages/xpub-ui/test/AppBar.test.js index 9a94b13fc8f8948367fbf16a708f59b0d91eb96a..25c7946b6adf8fa703dd27701b83e14b55d46443 100644 --- a/packages/xpub-ui/test/AppBar.test.js +++ b/packages/xpub-ui/test/AppBar.test.js @@ -1,7 +1,6 @@ import React from 'react' -import { clone } from 'lodash' import { shallow } from 'enzyme' -import {Link, MemoryRouter} from 'react-router-dom' +import { Link, MemoryRouter } from 'react-router-dom' import renderer from 'react-test-renderer' import AppBar from '../src/molecules/AppBar' @@ -16,24 +15,28 @@ const props = { function makeWrapper(extraProps = {}) { return shallow( - <MemoryRouter> - <AppBar {...props} {...extraProps}/> - </MemoryRouter> - ).dive().dive() + <MemoryRouter> + <AppBar {...props} {...extraProps} /> + </MemoryRouter>, + ) + .dive() + .dive() } describe('AppBar', () => { test('Snapshot', () => { - const tree = renderer.create( + const tree = renderer + .create( <MemoryRouter> <AppBar {...props} /> - </MemoryRouter> - ).toJSON() + </MemoryRouter>, + ) + .toJSON() expect(tree).toMatchSnapshot() }) test("Should link the brand to '/' if no brand link is given", () => { - const wrapper = makeWrapper({brandLink: undefined}) + const wrapper = makeWrapper({ brandLink: undefined }) const brand = wrapper.childAt(0) expect(brand.prop('to')).toBe('/') @@ -54,7 +57,7 @@ describe('AppBar', () => { }) test('Should not display the username if there is none given', () => { - const wrapper = makeWrapper({userName: undefined}) + const wrapper = makeWrapper({ userName: undefined }) const rightArea = wrapper.childAt(1) @@ -68,14 +71,14 @@ describe('AppBar', () => { expect(rightArea.children()).toHaveLength(2) const userName = rightArea.childAt(0) - expect(userName.text()).toBe("<Icon />some name") + expect(userName.text()).toBe('<Icon />some name') }) test('Should display the login link if no username is given', () => { - const wrapper = makeWrapper({userName: undefined}) + const wrapper = makeWrapper({ userName: undefined }) const rightArea = wrapper.childAt(1) - const logLink = rightArea.childAt(0) // first el if there is no username + const logLink = rightArea.childAt(0) // first el if there is no username expect(logLink.is(Link)).toBeTruthy() expect(logLink.prop('to')).toBe(props.loginLink) diff --git a/packages/xpub-ui/test/Menu.test.js b/packages/xpub-ui/test/Menu.test.js index 536d756318a417ddb9d735a7a02d3879165cd425..b71f3a4d45edc01ed42381be5777f074fcbe3e16 100644 --- a/packages/xpub-ui/test/Menu.test.js +++ b/packages/xpub-ui/test/Menu.test.js @@ -5,20 +5,15 @@ import renderer from 'react-test-renderer' import Menu from '../src/atoms/Menu' const props = { - options: [ - { value: 'foo', label: 'Foo' }, - { value: 'bar', label: 'Bar' }, - ], - value: 'foo' + options: [{ label: 'Foo', value: 'foo' }, { label: 'Bar', value: 'bar' }], + value: 'foo', } const wrapper = shallow(<Menu {...props} />) describe('Menu', () => { test('Snapshot', () => { - const tree = renderer.create( - <Menu {...props} /> - ).toJSON() + const tree = renderer.create(<Menu {...props} />).toJSON() expect(tree).toMatchSnapshot() }) diff --git a/packages/xpub-ui/test/Radio.test.js b/packages/xpub-ui/test/Radio.test.js index cadded1ba8caad7c98172b80bc5483077b591128..35d3309950474493fef25b8ca1ab14dc0d792ab6 100644 --- a/packages/xpub-ui/test/Radio.test.js +++ b/packages/xpub-ui/test/Radio.test.js @@ -9,16 +9,14 @@ const props = { label: 'TestLabel', name: 'TestName', required: true, - value: 'TestValue' + value: 'TestValue', } const wrapper = shallow(<Radio {...props} />) describe('Radio', () => { test('Snapshot', () => { - const tree = renderer.create( - <Radio {...props} /> - ).toJSON() + const tree = renderer.create(<Radio {...props} />).toJSON() expect(tree).toMatchSnapshot() }) diff --git a/packages/xpub-ui/test/RadioGroup.test.js b/packages/xpub-ui/test/RadioGroup.test.js index be8884cadb14a40a03f7f83122389816e58c5512..b6ff69ef39461862f79ff197e6d755e935fef36a 100644 --- a/packages/xpub-ui/test/RadioGroup.test.js +++ b/packages/xpub-ui/test/RadioGroup.test.js @@ -11,19 +11,19 @@ const props = { options: [ { label: 'Yes', - value: 'yes' + value: 'yes', }, { label: 'No', - value: 'no' + value: 'no', }, { label: 'Maybe', - value: 'maybe' - } + value: 'maybe', + }, ], required: true, - value: undefined + value: undefined, } const wrapper = shallow(<RadioGroup {...props} />) @@ -31,9 +31,7 @@ const radios = wrapper.find(Radio) describe('Radio Group', () => { test('Snapshot', () => { - const tree = renderer.create( - <RadioGroup {...props} /> - ).toJSON() + const tree = renderer.create(<RadioGroup {...props} />).toJSON() expect(tree).toMatchSnapshot() }) @@ -49,7 +47,7 @@ describe('Radio Group', () => { const child = wrapper.childAt(i) expect(child.is(Radio)).toBeTruthy() - i++ + i += 1 } expect(radios).toHaveLength(len) @@ -68,7 +66,7 @@ describe('Radio Group', () => { expect(radioProps.name).toEqual(props.name) expect(radioProps.required).toEqual(props.required) - i++ + i += 1 } }) @@ -82,7 +80,7 @@ describe('Radio Group', () => { const radioProps = radio.props expect(radioProps.checked).toBeFalsy() - i++ + i += 1 } // With the first radio button selected @@ -106,7 +104,7 @@ describe('Radio Group', () => { expect(radioProps.checked).toBeFalsy() } - i++ + i += 1 } }) }) diff --git a/packages/xpub-ui/test/YesOrNo.test.js b/packages/xpub-ui/test/YesOrNo.test.js index d2256b133df002ceb0e73f5015b9f7dc1169089b..b893b903cce438c5fe4b62cf43c34e2cc8cde713 100644 --- a/packages/xpub-ui/test/YesOrNo.test.js +++ b/packages/xpub-ui/test/YesOrNo.test.js @@ -7,7 +7,7 @@ import RadioGroup from '../src/molecules/RadioGroup' const props = { name: 'TestName', - value: 'Maybe' + value: 'Maybe', } const wrapper = shallow(<YesOrNo {...props} />) @@ -15,9 +15,7 @@ const radio = wrapper.find(RadioGroup) describe('Yes or No', () => { test('Snapshot', () => { - const tree = renderer.create( - <YesOrNo {...props} /> - ).toJSON() + const tree = renderer.create(<YesOrNo {...props} />).toJSON() expect(tree).toMatchSnapshot() }) @@ -27,7 +25,7 @@ describe('Yes or No', () => { }) test('Passes the correct options', () => { - const options = radio.props().options + const { options } = radio.props() expect(options).toHaveLength(2) expect(options[0].value).toEqual('yes') @@ -38,12 +36,12 @@ describe('Yes or No', () => { }) test('Passes down the correct name', () => { - const name = radio.props().name + const { name } = radio.props() expect(name).toEqual(props.name) }) test('Passes down the correct value', () => { - const value = radio.props().value + const { value } = radio.props() expect(value).toEqual(props.value) }) }) diff --git a/packages/xpub-ui/test/config/transform.js b/packages/xpub-ui/test/config/transform.js index 4fc948d1f24c1712a09c22c86b55d1992533ae4e..7cc533c7f6c6251ce1b71bb5171ee6ef28991c4d 100644 --- a/packages/xpub-ui/test/config/transform.js +++ b/packages/xpub-ui/test/config/transform.js @@ -1,7 +1,3 @@ module.exports = require('babel-jest').createTransformer({ - presets: [ - 'env', - 'react', - 'stage-2' - ] -}); + presets: ['env', 'react', 'stage-2'], +}) diff --git a/packages/xpub-ui/test/setup/enzyme.js b/packages/xpub-ui/test/setup/enzyme.js index feb8347d96b58c50b631f3fa8f72bf7d882bdba9..7ae191afcbbe1d62f2497f8634fcfe952bb6b520 100644 --- a/packages/xpub-ui/test/setup/enzyme.js +++ b/packages/xpub-ui/test/setup/enzyme.js @@ -1,4 +1,4 @@ import Enzyme from 'enzyme' import Adapter from 'enzyme-adapter-react-15' -Enzyme.configure({adapter: new Adapter()}) \ No newline at end of file +Enzyme.configure({ adapter: new Adapter() }) diff --git a/packages/xpub-upload/src/upload.js b/packages/xpub-upload/src/upload.js index bd08981d9b957be1372e4e00ab0c9e080bd8dd24..7b20e02fd148541d51215fe4fa9bfe57fed71caa 100644 --- a/packages/xpub-upload/src/upload.js +++ b/packages/xpub-upload/src/upload.js @@ -6,8 +6,8 @@ export default file => dispatch => { data.append('file', file) const request = new XMLHttpRequest() - request.open('POST', endpoint + '/upload') - request.setRequestHeader('Authorization', 'Bearer ' + token()) + request.open('POST', `${endpoint}/upload`) + request.setRequestHeader('Authorization', `Bearer ${token()}`) request.setRequestHeader('Accept', 'text/plain') // the response is a URL request.send(data) diff --git a/packages/xpub-validators/src/index.js b/packages/xpub-validators/src/index.js index 9551785ef92c4b19c113b8f3acb17632c663588e..000381ff33a105109e20bbfac1f8758369e9e40f 100644 --- a/packages/xpub-validators/src/index.js +++ b/packages/xpub-validators/src/index.js @@ -1,12 +1,10 @@ import striptags from 'striptags' -export const split = (separator = ',') => value => { - return value ? value.split(separator) : [] -} +export const split = (separator = ',') => value => + value ? value.split(separator) : [] -export const join = (separator = ',') => value => { - return value ? value.join(separator) : value -} +export const join = (separator = ',') => value => + value ? value.join(separator) : value export const required = value => { if (value === undefined || value === '') { diff --git a/yarn.lock b/yarn.lock index 3fe7267b7a2430ef7fe2b510c17666e33a9bbf2f..2b376083bfaea68da73636620827d531beba4cd2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -563,7 +563,7 @@ babel-core@^6.0.0, babel-core@^6.26.0: slash "^1.0.0" source-map "^0.5.6" -babel-eslint@^8.0.1: +babel-eslint@^8.0.2: version "8.0.3" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.0.3.tgz#f29ecf02336be438195325cd47c468da81ee4e98" dependencies: @@ -3172,6 +3172,10 @@ eslint-plugin-import@^2.8.0: minimatch "^3.0.3" read-pkg-up "^2.0.0" +eslint-plugin-jest@^21.4.0: + version "21.4.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-21.4.0.tgz#8d8a1166c92a7530217d201a5d440a1f4a042f61" + eslint-plugin-jsx-a11y@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.0.2.tgz#659277a758b036c305a7e4a13057c301cd3be73f" @@ -3228,7 +3232,7 @@ eslint-scope@^3.7.1: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint@^4.11.0: +eslint@^4.12.0: version "4.12.1" resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.12.1.tgz#5ec1973822b4a066b353770c3c6d69a2a188e880" dependencies: @@ -7505,6 +7509,13 @@ postcss-selector-parser@^3.1.0: indexes-of "^1.0.1" uniq "^1.0.1" +postcss-sorting@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/postcss-sorting/-/postcss-sorting-3.1.0.tgz#af7c90ee73ad12569a57664eaf06735c2e25bec0" + dependencies: + lodash "^4.17.4" + postcss "^6.0.13" + postcss-svgo@^2.1.1: version "2.1.6" resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-2.1.6.tgz#b6df18aa613b666e133f08adb5219c2684ac108d" @@ -7543,7 +7554,7 @@ postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0 source-map "^0.5.6" supports-color "^3.2.3" -postcss@^6.0.1, postcss@^6.0.13, postcss@^6.0.14, postcss@^6.0.3, postcss@^6.0.6, postcss@^6.0.8: +postcss@^6.0.1, postcss@^6.0.11, postcss@^6.0.13, postcss@^6.0.14, postcss@^6.0.3, postcss@^6.0.6, postcss@^6.0.8: version "6.0.14" resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.14.tgz#5534c72114739e75d0afcf017db853099f562885" dependencies: @@ -9868,15 +9879,31 @@ style-search@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902" -stylelint-config-recommended@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stylelint-config-recommended/-/stylelint-config-recommended-1.0.0.tgz#752c17fc68fa64cd5e7589e24f6e46e77e14a735" +stylelint-config-pubsweet@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/stylelint-config-pubsweet/-/stylelint-config-pubsweet-0.0.2.tgz#e3981f91dc5462cd91d1dc0c43e1ce314e62fdec" + dependencies: + stylelint "^8.2.0" + stylelint-config-standard "^18.0.0" + stylelint-order "^0.7.0" + +stylelint-config-recommended@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/stylelint-config-recommended/-/stylelint-config-recommended-2.0.0.tgz#560a028e81ea3ca8894b9a8eef4c0e05ac60e090" -stylelint-config-standard@^17.0.0: - version "17.0.0" - resolved "https://registry.yarnpkg.com/stylelint-config-standard/-/stylelint-config-standard-17.0.0.tgz#42103a090054ee2a3dde9ecaed55e5d4d9d059fc" +stylelint-config-standard@^18.0.0: + version "18.0.0" + resolved "https://registry.yarnpkg.com/stylelint-config-standard/-/stylelint-config-standard-18.0.0.tgz#0d872b40fafdcddcf4188fb5b64ddb3887e8aefc" dependencies: - stylelint-config-recommended "^1.0.0" + stylelint-config-recommended "^2.0.0" + +stylelint-order@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/stylelint-order/-/stylelint-order-0.7.0.tgz#ceab5cbe24aa33fa63590024995395f6edfc9ab7" + dependencies: + lodash "^4.17.4" + postcss "^6.0.11" + postcss-sorting "^3.0.2" stylelint@^8.2.0: version "8.3.1"