Skip to content
Snippets Groups Projects
Commit 5140067b authored by Bogdan Cochior's avatar Bogdan Cochior
Browse files

Merge branch 'faraday-master' of gitlab.coko.foundation:xpub/xpub into faraday-master

# Conflicts:
#	packages/xpub-faraday/app/config/journal/submit-wizard.js
parents a8b820ea 5041a933
No related branches found
No related tags found
No related merge requests found
......@@ -7,7 +7,14 @@ import { reduxForm } from 'redux-form'
import { actions } from 'pubsweet-client'
import { required } from 'xpub-validators'
import { withRouter } from 'react-router-dom'
import { compose, withHandlers, getContext, lifecycle } from 'recompose'
import { selectCurrentUser } from 'xpub-selectors'
import {
compose,
withHandlers,
withProps,
getContext,
lifecycle,
} from 'recompose'
import { TextField, Menu, Icon, ValidatedField, Button } from '@pubsweet/ui'
import { addAuthor, getFragmentAuthors, setAuthors } from '../redux/authors'
......@@ -48,7 +55,22 @@ const MenuItem = ({ label, name, options }) => (
</div>
)
const AuthorAdder = ({ authors, handleSubmit, ...rest }) => (
const Label = ({ label, value }) => (
<div className={classnames(classes['label-container'])}>
<span className={classnames(classes.label)}>{label}</span>
<span className={classnames(classes.value)}>{value}</span>
</div>
)
const DragHandle = () => (
<div className={classnames(classes['drag-handle'])}>
<Icon>chevron_up</Icon>
<Icon size={16}>menu</Icon>
<Icon>chevron_down</Icon>
</div>
)
const AuthorAdder = ({ authors, handleSubmit }) => (
<div className={classnames(classes.adder)}>
<Button onClick={handleSubmit} primary>
{authors.length === 0 ? '+ Add submitting author' : '+ Add author'}
......@@ -83,20 +105,41 @@ const AuthorAdder = ({ authors, handleSubmit, ...rest }) => (
</div>
)
const Label = ({ label, value }) => (
<div className={classnames(classes['label-container'])}>
<span className={classnames(classes.label)}>{label}</span>
<span className={classnames(classes.value)}>{value}</span>
</div>
)
const DragHandle = () => (
<div className={classnames(classes['drag-handle'])}>
<Icon>chevron_up</Icon>
<Icon size={16}>menu</Icon>
<Icon>chevron_down</Icon>
</div>
)
const Adder = compose(
connect(state => ({
currentUser: selectCurrentUser(state),
})),
withProps(({ currentUser }) => {
const { admin, email, username } = currentUser
if (!admin) {
return {
initialValues: {
author: {
email,
firstName: username,
},
},
}
}
}),
reduxForm({
form: 'author',
onSubmit: (values, dispatch, { authors, addAuthor, reset, match }) => {
const collectionId = get(match, 'params.project')
const fragmentId = get(match, 'params.version')
const isFirstAuthor = authors.length === 0
addAuthor(
{
...values.author,
isSubmitting: isFirstAuthor,
isCorresponding: isFirstAuthor,
},
collectionId,
fragmentId,
).then(reset)
},
}),
)(AuthorAdder)
const Author = ({
firstName,
......@@ -163,27 +206,6 @@ const Author = ({
</div>
)
const Adder = compose(
reduxForm({
form: 'author',
destroyOnUnmount: false,
onSubmit: (values, dispatch, { authors, addAuthor, reset, match }) => {
const collectionId = get(match, 'params.project')
const fragmentId = get(match, 'params.version')
const isFirstAuthor = authors.length === 0
addAuthor(
{
...values.author,
isSubmitting: isFirstAuthor,
isCorresponding: isFirstAuthor,
},
collectionId,
fragmentId,
).then(reset)
},
})(AuthorAdder),
)
const Authors = ({
author,
authors,
......
import { get } from 'lodash'
import { actions } from 'pubsweet-client'
import * as api from 'pubsweet-client/src/helpers/api'
import { change } from 'redux-form'
// constants
export const SET_AUTHORS = 'authors/SET_AUTHORS'
// actions
export const setAuthors = (authors, fragmentId) => ({
const _setAuthors = (authors, fragmentId) => ({
type: SET_AUTHORS,
authors,
fragmentId,
})
// actions
export const setAuthors = (authors, fragmentId) => dispatch => {
dispatch(_setAuthors(authors, fragmentId))
dispatch(change('wizard', 'authors', authors))
}
export const addAuthor = (author, collectionId, fragmentId) => dispatch =>
api
.create(`/fragments/${fragmentId}/authors`, author)
......
const bodyParser = require('body-parser')
const AuthorBackend = app => {
const authBearer = app.locals.passport.authenticate('bearer', {
let authBearer = app.locals.passport.authenticate('bearer', {
session: false,
})
if (process.env.NODE_ENV === 'test') {
authBearer = app.locals.passport.authenticate('anonymous')
}
app.post(
'/api/fragments/:fragmentId/authors',
authBearer,
bodyParser.json(),
async (req, res, next) => {
try {
if (!req.params.fragmentId) {
res.status(400).json({ error: 'Fragment ID is required' })
return
}
let fragment = await app.locals.models.Fragment.find(
req.params.fragmentId,
)
......@@ -24,19 +25,22 @@ const AuthorBackend = app => {
)
if (emailAuthors.length > 0) {
res.status(400).json({ error: 'Author already exists' })
res
.status(400)
.json({ error: 'Author with the same email already exists' })
return
}
const nameAuthors = fragment.authors.filter(
const submittingAuthors = fragment.authors.filter(
author =>
author.firstName === req.body.firstName &&
author.middleName === req.body.middleName &&
author.lastName === req.body.lastName,
author.isSubmitting === true &&
author.isSubmitting === req.body.isSubmitting,
)
if (nameAuthors.length > 0) {
res.status(400).json({ error: 'Author already exists' })
if (submittingAuthors.length > 0) {
res
.status(400)
.json({ error: 'There can only be one sumbitting author' })
return
}
}
......
......@@ -2,30 +2,21 @@ process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
process.env.SUPPRESS_NO_CONFIG_WARNING = true
const bodyParser = require('body-parser')
const express = require('express')
const supertest = require('supertest')
const component = require('..')
const author = {
first_name: 'marcel',
middle_name: 'sss',
last_name: 'iures',
email: 'email@ciment2.com',
affiliation: 'UTI',
country: '',
is_corresponding: true,
is_submitting: true,
save: jest.fn(),
}
const express = require('express')
const fixtures = require('./fixtures/fixtures')
const passport = require('passport')
const AnonymousStrategy = require('passport-anonymous').Strategy
function makeApp(response) {
const app = express()
app.use(bodyParser.json())
app.locals = {
passport: {
authenticate: jest.fn(() => () => Promise.resolve(true)),
},
}
// Passport strategies
app.use(passport.initialize())
passport.use('anonymous', new AnonymousStrategy())
app.locals.passport = passport
app.locals.models = {
Fragment: {
find: jest.fn(
......@@ -36,16 +27,43 @@ function makeApp(response) {
),
},
}
component.backend()(app)
return supertest(app)
}
describe('Author Backend API', () => {
it('should return error if fragment is not found', () =>
makeApp(new Error('Not Found'))
.post('/api/fragments/cf7b9ea6-47ac-4188-b0ef-f89cc17364fe/authors')
.set('Content-Type', 'application/json')
// .set('Authentication', `Bearer ${token}`)
.send(author)
.expect(404, '"error": "Fragment not found"'))
it('should return an error if fragment is not found', () => {
const error = new Error()
error.name = 'NotFoundError'
error.status = 404
return makeApp(error)
.post('/api/fragments/123/authors')
.send(fixtures.author)
.expect(404, '{"error":"Fragment not found"}')
})
it('should return an error if an author field is invalid', () => {
const error = new Error()
error.name = 'ValidationError'
error.status = 404
error.details = []
error.details.push({ message: 'firstName is required' })
return makeApp(error)
.post('/api/fragments/123/authors')
.send(fixtures.invalidAuthor)
.expect(404, '{"error":"firstName is required"}')
})
it('should return an error if an author already exists with the same email', () =>
makeApp(fixtures.fragment)
.post('/api/fragments/123-valid-id/authors')
.send(fixtures.author)
.expect(400, '{"error":"Author with the same email already exists"}'))
it('should return an error if there already is a submitting author', () =>
makeApp(fixtures.fragment)
.post('/api/fragments/123-valid-id/authors')
.send(fixtures.newSubmittingAuthor)
.expect(400, '{"error":"There can only be one sumbitting author"}'))
})
const author = {
firstName: 'Andrew',
middleName: '',
lastName: 'Smith',
email: 'email@email.com',
affiliation: 'University',
country: '',
isCorresponding: true,
isSubmitting: true,
}
const invalidAuthor = {
firstName: '',
middleName: '',
lastName: 'Jones',
email: 'email2@email.com',
affiliation: 'University',
country: '',
isCorresponding: false,
isSubmitting: false,
}
const newSubmittingAuthor = {
firstName: 'Andrew',
middleName: '',
lastName: 'Smith',
email: 'email3@email.com',
affiliation: 'University',
country: '',
isCorresponding: false,
isSubmitting: true,
}
const fragment = {
type: 'fragment',
fragmentType: 'blogpost',
title: 'Just your regular blogpost',
source: '<blog></blog>',
presentation: '<p></p>',
authors: [author],
save: jest.fn(),
}
module.exports = {
author,
invalidAuthor,
fragment,
newSubmittingAuthor,
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment