Skip to content
Snippets Groups Projects
Commit 36f0725c authored by Alexandru Munteanu's avatar Alexandru Munteanu
Browse files

feat(adminUsers): add error handling

parent 39f8a6f3
No related branches found
No related tags found
3 merge requests!222Sprint #26,!217Sprint #26,!200Component user add user
Showing
with 138 additions and 106 deletions
...@@ -51,6 +51,7 @@ export { default as EditorialReportCard } from './EditorialReportCard' ...@@ -51,6 +51,7 @@ export { default as EditorialReportCard } from './EditorialReportCard'
export { default as ReviewerReportAuthor } from './ReviewerReportAuthor' export { default as ReviewerReportAuthor } from './ReviewerReportAuthor'
export { default as PasswordValidation } from './PasswordValidation' export { default as PasswordValidation } from './PasswordValidation'
export { default as MenuCountry } from './MenuCountry' export { default as MenuCountry } from './MenuCountry'
export { default as ValidatedMenuField } from './ValidatedMenuField'
export { SubmitRevision } from './submissionRevision' export { SubmitRevision } from './submissionRevision'
......
import React, { Fragment } from 'react'
import { compose, withStateHandlers } from 'recompose'
const MyMenu = ({ open, toggleMenu, field, form }) => (
<div onClick={toggleMenu}>
Click to open
{open && (
<Fragment>
<span onClick={() => form.setFieldValue(field.name, 1)}>Option 1</span>
<span onClick={() => form.setFieldValue(field.name, 2)}>Option 2</span>
<span onClick={() => form.setFieldValue(field.name, 3)}>Option 3</span>
</Fragment>
)}
</div>
)
export default compose(
withStateHandlers(
{ open: false },
{
toggleMenu: ({ open }) => () => ({
open: !open,
}),
},
),
)(MyMenu)
...@@ -6,6 +6,11 @@ import { MultiAction, SingleActionModal, FormModal } from './' ...@@ -6,6 +6,11 @@ import { MultiAction, SingleActionModal, FormModal } from './'
const OpenModal = ({ showModal, children }) => children(showModal) const OpenModal = ({ showModal, children }) => children(showModal)
const selectModalComponent = props => { const selectModalComponent = props => {
if (props.component) {
return {
modalComponent: props.component,
}
}
if (props.single) { if (props.single) {
return { return {
modalComponent: SingleActionModal, modalComponent: SingleActionModal,
......
export { default as OpenModal } from './OpenModal' export { default as OpenModal } from './OpenModal'
export { default as FormModal } from './FormModal'
export { default as MultiAction } from './MultiAction' export { default as MultiAction } from './MultiAction'
export { default as SingleActionModal } from './SingleActionModal' export { default as SingleActionModal } from './SingleActionModal'
const Chance = require('chance')
const { omit } = require('lodash')
const Notification = require('./notifications/notification') const Notification = require('./notifications/notification')
const chance = new Chance() const { parseUserFromAdmin } = require('./user')
const resolvers = { const resolvers = {
Mutation: { Mutation: {
async addUserWithConfirmationEmail(_, { input }, ctx) { async addUserAsAdmin(_, { input }, ctx) {
const reqUser = await ctx.connectors.User.fetchOne(ctx.user, ctx) const reqUser = await ctx.connectors.User.fetchOne(ctx.user, ctx)
if (!reqUser.admin) { if (!reqUser.admin) {
throw new Error('Unauthorized') throw new Error('Unauthorized')
} }
const roles = {
admin: false,
editorInChief: false,
handlingEditor: false,
}
if (input.role !== 'author') {
roles[input.role] = true
}
input = {
...omit(input, ['role']),
...roles,
isActive: true,
isConfirmed: false,
notifications: {
email: {
system: true,
user: true,
},
},
accessTokens: {
confirmation: chance.hash(),
unsubscribe: chance.hash(),
},
}
try { try {
const user = await ctx.connectors.User.create(input, ctx) const user = await ctx.connectors.User.create(
parseUserFromAdmin(input),
ctx,
)
const notification = new Notification(user) const notification = new Notification(user)
await notification.notifyUserAddedByAdmin(input.role) await notification.notifyUserAddedByAdmin(input.role)
return user
} catch (e) {
return e
}
},
async editUserAsAdmin(_, { id, input }, ctx) {
try {
const user = await ctx.connectors.User.update(
id,
parseUserFromAdmin(input),
ctx,
)
return user return user
} catch (e) { } catch (e) {
return e return e
......
module.exports = ` module.exports = `
type Creasta {
id: String!
name: String
}
extend type User { extend type User {
affiliation: String affiliation: String
country: String country: String
...@@ -22,11 +17,13 @@ module.exports = ` ...@@ -22,11 +17,13 @@ module.exports = `
title: String title: String
country: String country: String
affiliation: String affiliation: String
role: AllowedRole! role: AllowedRole
isActive: Boolean
} }
extend type Mutation { extend type Mutation {
addUserWithConfirmationEmail(input: UserInput!): User addUserAsAdmin(id:ID!, input: UserInput!): User
editUserAsAdmin(id: ID!, input: UserInput!): User
} }
enum AllowedRole { enum AllowedRole {
......
const Chance = require('chance')
const { omit } = require('lodash')
const chance = new Chance()
module.exports = {
parseUserFromAdmin: input => {
const roles = {
admin: false,
editorInChief: false,
handlingEditor: false,
}
if (input.role !== 'author') {
roles[input.role] = true
}
return {
...omit(input, ['role']),
...roles,
isActive: true,
isConfirmed: false,
notifications: {
email: {
system: true,
user: true,
},
},
accessTokens: {
confirmation: chance.hash(),
unsubscribe: chance.hash(),
},
}
},
}
...@@ -20,30 +20,25 @@ import { ...@@ -20,30 +20,25 @@ import {
IconButton, IconButton,
RowOverrideAlert, RowOverrideAlert,
ItemOverrideAlert, ItemOverrideAlert,
ValidatedMenuField,
withRoles, withRoles,
withFetching, withFetching,
withCountries, withCountries,
} from 'pubsweet-component-faraday-ui' } from 'pubsweet-component-faraday-ui'
import ValidatedMenuField from './ValidatedMenuField'
const FormModal = ({ const FormModal = ({
edit,
user,
roles, roles,
title, title,
titles, titles,
onClose, onClose,
subtitle, onSubmit,
onConfirm, onConfirm,
countries, countries,
confirmText = 'OK',
cancelText = 'Cancel',
onSubmit,
initialValues,
//
isFetching, isFetching,
fetchingError, fetchingError,
initialValues,
confirmText = 'OK',
cancelText = 'Cancel',
}) => ( }) => (
<Root> <Root>
<IconButton icon="x" onClick={onClose} right={5} secondary top={5} /> <IconButton icon="x" onClick={onClose} right={5} secondary top={5} />
...@@ -54,11 +49,11 @@ const FormModal = ({ ...@@ -54,11 +49,11 @@ const FormModal = ({
validate={values => { validate={values => {
const errors = {} const errors = {}
if (values.email === '') { if (get(values, 'email', '') === '') {
errors.email = 'Required' errors.email = 'Required'
} }
if (values.affiliation === '') { if (get(values, 'affiliation', '') === '') {
errors.affiliation = 'Required' errors.affiliation = 'Required'
} }
...@@ -72,6 +67,7 @@ const FormModal = ({ ...@@ -72,6 +67,7 @@ const FormModal = ({
<Label required>Email</Label> <Label required>Email</Label>
<ValidatedFieldFormik <ValidatedFieldFormik
component={TextField} component={TextField}
inline
name="email" name="email"
validate={[required]} validate={[required]}
/> />
...@@ -85,11 +81,19 @@ const FormModal = ({ ...@@ -85,11 +81,19 @@ const FormModal = ({
<Row mb={2}> <Row mb={2}>
<Item mr={1} vertical> <Item mr={1} vertical>
<Label>First Name</Label> <Label>First Name</Label>
<ValidatedFieldFormik component={TextField} name="firstName" /> <ValidatedFieldFormik
component={TextField}
inline
name="firstName"
/>
</Item> </Item>
<Item ml={1} vertical> <Item ml={1} vertical>
<Label>Last Name</Label> <Label>Last Name</Label>
<ValidatedFieldFormik component={TextField} name="lastName" /> <ValidatedFieldFormik
component={TextField}
inline
name="lastName"
/>
</Item> </Item>
</Row> </Row>
...@@ -104,10 +108,14 @@ const FormModal = ({ ...@@ -104,10 +108,14 @@ const FormModal = ({
</ItemOverrideAlert> </ItemOverrideAlert>
</RowOverrideAlert> </RowOverrideAlert>
<Row mb={!edit && 3}> <Row mb={3}>
<Item vertical> <Item vertical>
<Label required>Affiliation</Label> <Label required>Affiliation</Label>
<ValidatedFieldFormik component={TextField} name="affiliation" /> <ValidatedFieldFormik
component={TextField}
inline
name="affiliation"
/>
</Item> </Item>
</Row> </Row>
...@@ -135,6 +143,9 @@ const FormModal = ({ ...@@ -135,6 +143,9 @@ const FormModal = ({
// #region FormHelpers // #region FormHelpers
const setInitialRole = a => { const setInitialRole = a => {
if (get(a, 'admin')) {
return 'admin'
}
if (get(a, 'handlingEditor')) { if (get(a, 'handlingEditor')) {
return 'handlingEditor' return 'handlingEditor'
} }
...@@ -144,14 +155,6 @@ const setInitialRole = a => { ...@@ -144,14 +155,6 @@ const setInitialRole = a => {
return 'author' return 'author'
} }
// const parseValues = ({ email, role, ...rest }) => ({
// email,
// username: email,
// admin: role === 'admin',
// editorInChief: role === 'editorInChief',
// handlingEditor: role === 'handlingEditor',
// ...rest,
// })
// #endregion // #endregion
export default compose( export default compose(
......
...@@ -15,7 +15,6 @@ import { ...@@ -15,7 +15,6 @@ import {
Pagination, Pagination,
ActionLink, ActionLink,
handleError, handleError,
withFetching,
withPagination, withPagination,
} from 'pubsweet-component-faraday-ui' } from 'pubsweet-component-faraday-ui'
......
...@@ -6,10 +6,12 @@ import { ...@@ -6,10 +6,12 @@ import {
IconButton, IconButton,
} from 'pubsweet-component-faraday-ui' } from 'pubsweet-component-faraday-ui'
import AdminUserForm from './AdminUserForm'
const OpenUserForm = ({ edit, user, onSubmit, modalKey }) => ( const OpenUserForm = ({ edit, user, onSubmit, modalKey }) => (
<OpenModal <OpenModal
component={AdminUserForm}
edit={edit} edit={edit}
formModal
modalKey={modalKey} modalKey={modalKey}
onSubmit={onSubmit} onSubmit={onSubmit}
user={user} user={user}
......
...@@ -5,6 +5,8 @@ import { compose, withHandlers, withProps } from 'recompose' ...@@ -5,6 +5,8 @@ import { compose, withHandlers, withProps } from 'recompose'
const userFragment = gql` const userFragment = gql`
fragment userDetails on User { fragment userDetails on User {
id id
handlingEditor
editorInChief
admin admin
email email
title title
...@@ -25,46 +27,73 @@ const getUsersQuery = gql` ...@@ -25,46 +27,73 @@ const getUsersQuery = gql`
${userFragment} ${userFragment}
` `
const addUserMutation = gql` const addUserAsAdmin = gql`
mutation addUser($user: UserInput) { mutation addUserAsAdmin($id: ID!, $input: UserInput!) {
createUser(input: $user) { addUserAsAdmin(id: $id, input: $input) {
...userDetails ...userDetails
} }
} }
${userFragment} ${userFragment}
` `
const updateUserMutation = gql` const editUserAsAdmin = gql`
mutation updateUser($id: ID, $input: UserInput) { mutation editUserAsAdmin($id: ID!, $input: UserInput!) {
updateUser(id: $id, input: $input) { editUserAsAdmin(id: $id, input: $input) {
...userDetails ...userDetails
} }
} }
${userFragment} ${userFragment}
` `
const parseFormValues = ({ admin, ...input }) => input
export default compose( export default compose(
graphql(getUsersQuery), graphql(getUsersQuery),
graphql(addUserMutation, { graphql(addUserAsAdmin, {
name: 'addUser', name: 'addUser',
options: {
refetchQueries: [{ query: getUsersQuery }],
},
}), }),
graphql(updateUserMutation, { graphql(editUserAsAdmin, {
name: 'updateUser', name: 'updateUser',
}), }),
withHandlers({ withHandlers({
addUser: ({ addUser }) => (values, props) => {}, addUser: ({ addUser }) => (
{ __typename, id, admin, ...input },
{ props: { hideModal, setFetching } },
) => {
setFetching(true)
addUser({
variables: {
id,
input: {
...input,
username: input.email,
},
},
}).then(() => {
setFetching(false)
hideModal()
})
},
updateUser: ({ updateUser }) => ( updateUser: ({ updateUser }) => (
{ __typename, id, ...formValues }, { __typename, id, admin, handlingEditor, editorInChief, ...input },
{ props: { hideModal } }, { props: { hideModal, setFetching, setError } },
) => { ) => {
setFetching(true)
updateUser({ updateUser({
variables: { variables: {
id, id,
input: parseFormValues(formValues), input,
}, },
}).then(hideModal) })
.then(() => {
setFetching(false)
hideModal()
})
.catch(e => {
setFetching(false)
setError(e.message)
})
}, },
}), }),
withProps(({ data }) => ({ withProps(({ data }) => ({
......
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