From 36f0725ccdb0a1a4f3d7b558561e7ed6b4b635c6 Mon Sep 17 00:00:00 2001
From: malexsan <alexandru.munt@gmail.com>
Date: Wed, 12 Dec 2018 13:27:12 +0200
Subject: [PATCH] feat(adminUsers): add error handling

---
 .../src/{modals => }/ValidatedMenuField.js    |  0
 packages/component-faraday-ui/src/index.js    |  1 +
 .../component-faraday-ui/src/modals/MyMenu.js | 26 --------
 .../src/modals/OpenModal.js                   |  5 ++
 .../component-faraday-ui/src/modals/index.js  |  1 -
 packages/component-user/resolvers.js          | 51 +++++++---------
 packages/component-user/typeDefs.js           | 11 ++--
 packages/component-user/user.js               | 34 +++++++++++
 .../src/components/Admin/AdminUserForm.js}    | 51 ++++++++--------
 .../src/components/Admin/AdminUsers.js        |  1 -
 .../src/components/Admin/OpenUserForm.js      |  4 +-
 .../src/components/Admin/withUsersGQL.js      | 59 ++++++++++++++-----
 12 files changed, 138 insertions(+), 106 deletions(-)
 rename packages/component-faraday-ui/src/{modals => }/ValidatedMenuField.js (100%)
 delete mode 100644 packages/component-faraday-ui/src/modals/MyMenu.js
 rename packages/{component-faraday-ui/src/modals/FormModal.js => components-faraday/src/components/Admin/AdminUserForm.js} (86%)

diff --git a/packages/component-faraday-ui/src/modals/ValidatedMenuField.js b/packages/component-faraday-ui/src/ValidatedMenuField.js
similarity index 100%
rename from packages/component-faraday-ui/src/modals/ValidatedMenuField.js
rename to packages/component-faraday-ui/src/ValidatedMenuField.js
diff --git a/packages/component-faraday-ui/src/index.js b/packages/component-faraday-ui/src/index.js
index 2d3859c78..6d5f3b1be 100644
--- a/packages/component-faraday-ui/src/index.js
+++ b/packages/component-faraday-ui/src/index.js
@@ -51,6 +51,7 @@ export { default as EditorialReportCard } from './EditorialReportCard'
 export { default as ReviewerReportAuthor } from './ReviewerReportAuthor'
 export { default as PasswordValidation } from './PasswordValidation'
 export { default as MenuCountry } from './MenuCountry'
+export { default as ValidatedMenuField } from './ValidatedMenuField'
 
 export { SubmitRevision } from './submissionRevision'
 
diff --git a/packages/component-faraday-ui/src/modals/MyMenu.js b/packages/component-faraday-ui/src/modals/MyMenu.js
deleted file mode 100644
index 9fe37eb41..000000000
--- a/packages/component-faraday-ui/src/modals/MyMenu.js
+++ /dev/null
@@ -1,26 +0,0 @@
-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)
diff --git a/packages/component-faraday-ui/src/modals/OpenModal.js b/packages/component-faraday-ui/src/modals/OpenModal.js
index 16ac00971..12c944512 100644
--- a/packages/component-faraday-ui/src/modals/OpenModal.js
+++ b/packages/component-faraday-ui/src/modals/OpenModal.js
@@ -6,6 +6,11 @@ import { MultiAction, SingleActionModal, FormModal } from './'
 const OpenModal = ({ showModal, children }) => children(showModal)
 
 const selectModalComponent = props => {
+  if (props.component) {
+    return {
+      modalComponent: props.component,
+    }
+  }
   if (props.single) {
     return {
       modalComponent: SingleActionModal,
diff --git a/packages/component-faraday-ui/src/modals/index.js b/packages/component-faraday-ui/src/modals/index.js
index f45d22615..fb4d8875a 100644
--- a/packages/component-faraday-ui/src/modals/index.js
+++ b/packages/component-faraday-ui/src/modals/index.js
@@ -1,4 +1,3 @@
 export { default as OpenModal } from './OpenModal'
-export { default as FormModal } from './FormModal'
 export { default as MultiAction } from './MultiAction'
 export { default as SingleActionModal } from './SingleActionModal'
diff --git a/packages/component-user/resolvers.js b/packages/component-user/resolvers.js
index 3d04170be..71f393a2b 100644
--- a/packages/component-user/resolvers.js
+++ b/packages/component-user/resolvers.js
@@ -1,47 +1,36 @@
-const Chance = require('chance')
-const { omit } = require('lodash')
 const Notification = require('./notifications/notification')
 
-const chance = new Chance()
+const { parseUserFromAdmin } = require('./user')
+
 const resolvers = {
   Mutation: {
-    async addUserWithConfirmationEmail(_, { input }, ctx) {
+    async addUserAsAdmin(_, { input }, ctx) {
       const reqUser = await ctx.connectors.User.fetchOne(ctx.user, ctx)
       if (!reqUser.admin) {
         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 {
-        const user = await ctx.connectors.User.create(input, ctx)
+        const user = await ctx.connectors.User.create(
+          parseUserFromAdmin(input),
+          ctx,
+        )
         const notification = new Notification(user)
         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
       } catch (e) {
         return e
diff --git a/packages/component-user/typeDefs.js b/packages/component-user/typeDefs.js
index c6f217394..b20d4d078 100644
--- a/packages/component-user/typeDefs.js
+++ b/packages/component-user/typeDefs.js
@@ -1,9 +1,4 @@
 module.exports = `
-  type Creasta {
-    id: String!
-    name: String
-  }
-
   extend type User {
     affiliation: String
     country: String
@@ -22,11 +17,13 @@ module.exports = `
     title: String
     country: String
     affiliation: String
-    role: AllowedRole!
+    role: AllowedRole
+    isActive: Boolean
   }
 
   extend type Mutation {
-    addUserWithConfirmationEmail(input: UserInput!): User
+    addUserAsAdmin(id:ID!, input: UserInput!): User
+    editUserAsAdmin(id: ID!, input: UserInput!): User
   }
 
   enum AllowedRole {
diff --git a/packages/component-user/user.js b/packages/component-user/user.js
index e69de29bb..07a5b0657 100644
--- a/packages/component-user/user.js
+++ b/packages/component-user/user.js
@@ -0,0 +1,34 @@
+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(),
+      },
+    }
+  },
+}
diff --git a/packages/component-faraday-ui/src/modals/FormModal.js b/packages/components-faraday/src/components/Admin/AdminUserForm.js
similarity index 86%
rename from packages/component-faraday-ui/src/modals/FormModal.js
rename to packages/components-faraday/src/components/Admin/AdminUserForm.js
index af161bf39..4a3c3bba4 100644
--- a/packages/component-faraday-ui/src/modals/FormModal.js
+++ b/packages/components-faraday/src/components/Admin/AdminUserForm.js
@@ -20,30 +20,25 @@ import {
   IconButton,
   RowOverrideAlert,
   ItemOverrideAlert,
+  ValidatedMenuField,
   withRoles,
   withFetching,
   withCountries,
 } from 'pubsweet-component-faraday-ui'
 
-import ValidatedMenuField from './ValidatedMenuField'
-
 const FormModal = ({
-  edit,
-  user,
   roles,
   title,
   titles,
   onClose,
-  subtitle,
+  onSubmit,
   onConfirm,
   countries,
-  confirmText = 'OK',
-  cancelText = 'Cancel',
-  onSubmit,
-  initialValues,
-  //
   isFetching,
   fetchingError,
+  initialValues,
+  confirmText = 'OK',
+  cancelText = 'Cancel',
 }) => (
   <Root>
     <IconButton icon="x" onClick={onClose} right={5} secondary top={5} />
@@ -54,11 +49,11 @@ const FormModal = ({
       validate={values => {
         const errors = {}
 
-        if (values.email === '') {
+        if (get(values, 'email', '') === '') {
           errors.email = 'Required'
         }
 
-        if (values.affiliation === '') {
+        if (get(values, 'affiliation', '') === '') {
           errors.affiliation = 'Required'
         }
 
@@ -72,6 +67,7 @@ const FormModal = ({
               <Label required>Email</Label>
               <ValidatedFieldFormik
                 component={TextField}
+                inline
                 name="email"
                 validate={[required]}
               />
@@ -85,11 +81,19 @@ const FormModal = ({
           <Row mb={2}>
             <Item mr={1} vertical>
               <Label>First Name</Label>
-              <ValidatedFieldFormik component={TextField} name="firstName" />
+              <ValidatedFieldFormik
+                component={TextField}
+                inline
+                name="firstName"
+              />
             </Item>
             <Item ml={1} vertical>
               <Label>Last Name</Label>
-              <ValidatedFieldFormik component={TextField} name="lastName" />
+              <ValidatedFieldFormik
+                component={TextField}
+                inline
+                name="lastName"
+              />
             </Item>
           </Row>
 
@@ -104,10 +108,14 @@ const FormModal = ({
             </ItemOverrideAlert>
           </RowOverrideAlert>
 
-          <Row mb={!edit && 3}>
+          <Row mb={3}>
             <Item vertical>
               <Label required>Affiliation</Label>
-              <ValidatedFieldFormik component={TextField} name="affiliation" />
+              <ValidatedFieldFormik
+                component={TextField}
+                inline
+                name="affiliation"
+              />
             </Item>
           </Row>
 
@@ -135,6 +143,9 @@ const FormModal = ({
 
 // #region FormHelpers
 const setInitialRole = a => {
+  if (get(a, 'admin')) {
+    return 'admin'
+  }
   if (get(a, 'handlingEditor')) {
     return 'handlingEditor'
   }
@@ -144,14 +155,6 @@ const setInitialRole = a => {
   return 'author'
 }
 
-// const parseValues = ({ email, role, ...rest }) => ({
-//   email,
-//   username: email,
-//   admin: role === 'admin',
-//   editorInChief: role === 'editorInChief',
-//   handlingEditor: role === 'handlingEditor',
-//   ...rest,
-// })
 // #endregion
 
 export default compose(
diff --git a/packages/components-faraday/src/components/Admin/AdminUsers.js b/packages/components-faraday/src/components/Admin/AdminUsers.js
index 0e0555f57..f9a925292 100644
--- a/packages/components-faraday/src/components/Admin/AdminUsers.js
+++ b/packages/components-faraday/src/components/Admin/AdminUsers.js
@@ -15,7 +15,6 @@ import {
   Pagination,
   ActionLink,
   handleError,
-  withFetching,
   withPagination,
 } from 'pubsweet-component-faraday-ui'
 
diff --git a/packages/components-faraday/src/components/Admin/OpenUserForm.js b/packages/components-faraday/src/components/Admin/OpenUserForm.js
index 847237c69..ae406374e 100644
--- a/packages/components-faraday/src/components/Admin/OpenUserForm.js
+++ b/packages/components-faraday/src/components/Admin/OpenUserForm.js
@@ -6,10 +6,12 @@ import {
   IconButton,
 } from 'pubsweet-component-faraday-ui'
 
+import AdminUserForm from './AdminUserForm'
+
 const OpenUserForm = ({ edit, user, onSubmit, modalKey }) => (
   <OpenModal
+    component={AdminUserForm}
     edit={edit}
-    formModal
     modalKey={modalKey}
     onSubmit={onSubmit}
     user={user}
diff --git a/packages/components-faraday/src/components/Admin/withUsersGQL.js b/packages/components-faraday/src/components/Admin/withUsersGQL.js
index b9aab6051..d15b4ad5c 100644
--- a/packages/components-faraday/src/components/Admin/withUsersGQL.js
+++ b/packages/components-faraday/src/components/Admin/withUsersGQL.js
@@ -5,6 +5,8 @@ import { compose, withHandlers, withProps } from 'recompose'
 const userFragment = gql`
   fragment userDetails on User {
     id
+    handlingEditor
+    editorInChief
     admin
     email
     title
@@ -25,46 +27,73 @@ const getUsersQuery = gql`
   ${userFragment}
 `
 
-const addUserMutation = gql`
-  mutation addUser($user: UserInput) {
-    createUser(input: $user) {
+const addUserAsAdmin = gql`
+  mutation addUserAsAdmin($id: ID!, $input: UserInput!) {
+    addUserAsAdmin(id: $id, input: $input) {
       ...userDetails
     }
   }
   ${userFragment}
 `
 
-const updateUserMutation = gql`
-  mutation updateUser($id: ID, $input: UserInput) {
-    updateUser(id: $id, input: $input) {
+const editUserAsAdmin = gql`
+  mutation editUserAsAdmin($id: ID!, $input: UserInput!) {
+    editUserAsAdmin(id: $id, input: $input) {
       ...userDetails
     }
   }
   ${userFragment}
 `
 
-const parseFormValues = ({ admin, ...input }) => input
-
 export default compose(
   graphql(getUsersQuery),
-  graphql(addUserMutation, {
+  graphql(addUserAsAdmin, {
     name: 'addUser',
+    options: {
+      refetchQueries: [{ query: getUsersQuery }],
+    },
   }),
-  graphql(updateUserMutation, {
+  graphql(editUserAsAdmin, {
     name: 'updateUser',
   }),
   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 }) => (
-      { __typename, id, ...formValues },
-      { props: { hideModal } },
+      { __typename, id, admin, handlingEditor, editorInChief, ...input },
+      { props: { hideModal, setFetching, setError } },
     ) => {
+      setFetching(true)
       updateUser({
         variables: {
           id,
-          input: parseFormValues(formValues),
+          input,
         },
-      }).then(hideModal)
+      })
+        .then(() => {
+          setFetching(false)
+          hideModal()
+        })
+        .catch(e => {
+          setFetching(false)
+          setError(e.message)
+        })
     },
   }),
   withProps(({ data }) => ({
-- 
GitLab