浏览代码

changing to alpha-version of apollo 3

Tomi Cvetic 5 年之前
父节点
当前提交
ecf8c20120

+ 2 - 0
backend/src/resolvers.js

@@ -83,7 +83,9 @@ const Mutation = {
     return user
   },
   logout: async (parent, args, context, info) => {
+    console.log('trying to log out')
     context.response.clearCookie('token')
+    console.log('cookie cleared.')
     return 'Logged out.'
   },
   createTraining: async (parent, args, context, info) => {

+ 100 - 0
backend/src/user/resolvers.ts

@@ -0,0 +1,100 @@
+const { forwardTo } = require('prisma-binding')
+const bcrypt = require('bcryptjs')
+const jwt = require('jsonwebtoken')
+
+const LoginError = new Error('Login required.')
+const PermissionError = new Error('No permission.')
+
+const Query = {
+  currentUser: (parent, args, context, info) => {
+    if (!context.request.userId) throw LoginError
+    return context.db.query.user({
+      where: { id: context.request.userId }
+    }, info)
+  }
+}
+
+const Mutation = {
+  createUser: async (parent, args, context, info) => {
+    if (!context.request.userId) throw LoginError
+    const user = await context.db.query.user({
+      where: { id: context.request.userId }
+    }, info)
+    if (!user.)
+      const email = args.email.toLowerCase()
+    const password = await bcrypt.hash(args.password, 10)
+    return context.db.mutation.createUser(
+      {
+        data: {
+          ...args,
+          email,
+          password
+        }
+      },
+      info
+    )
+  },
+
+  signup: async (parent, args, ctx, info) => {
+    const email = args.email.toLowerCase()
+    const password = await bcrypt.hash(args.password, 10)
+    const user = await ctx.db.mutation.createUser(
+      {
+        data: {
+          ...args,
+          email,
+          password
+        }
+      },
+      info
+    )
+    const token = jwt.sign({ userId: user.id }, process.env.APP_SECRET)
+    ctx.response.cookie('token', token, {
+      httpOnly: true,
+      maxAge: 24 * 60 * 60 * 1000
+    })
+    return user
+  },
+
+  login: async (parent, args, context, info) => {
+    const { email, password } = args
+    const user = await context.db.query.user({ where: { email } })
+    if (!user) throw new Error('User not found')
+    const valid = await bcrypt.compare(password, user.password)
+    if (!valid) throw new Error('Invalid password')
+    const token = jwt.sign({ userId: user.id }, process.env.APP_SECRET)
+    context.response.cookie(
+      'token',
+      token,
+      {
+        httpOnly: true,
+        maxAge: 7 * 24 * 3600 * 1000
+      },
+      info
+    )
+    return user
+  },
+  logout: async (parent, args, context, info) => {
+    context.response.clearCookie('token')
+    return 'Logged out.'
+  },
+  requestPassword: async (parent, args, context, info) => {
+
+  },
+  resetPassword: async (parent, args, context, info) => {
+
+  },
+  updateUser: async (parent, args, context, info) => {
+
+  },
+  deleteUser: async (parent, args, context, info) => {
+
+  }
+}
+
+const resolvers = {
+  Query,
+  Mutation
+}
+
+module.exports = { resolvers }

+ 0 - 6
frontend/.babelrc

@@ -1,6 +0,0 @@
-{
-  "presets": [
-    "next/babel",
-    "@zeit/next-typescript/babel"
-  ]
-}

+ 1 - 1
frontend/babel.config.js

@@ -1,3 +1,3 @@
 module.exports = {
-  presets: ['next/babel', '@zeit/next-typescript/babel']
+  presets: ['next/babel']
 }

+ 21 - 0
frontend/components/user/DeleteUserButton.tsx

@@ -0,0 +1,21 @@
+import { useMutation } from "@apollo/react-hooks"
+import { USER_DELETE } from './graphql'
+import { SyntheticEvent } from "react"
+
+interface DeleteUserProps {
+  user: {
+    id: string
+  }
+  title?: string
+}
+
+const DeleteUserButton = ({ title, user: { id } }: DeleteUserProps) => {
+  const [deleteUser, { loading, error }] = useMutation(USER_DELETE)
+  return (
+    <button onClick={(event: SyntheticEvent) => {
+      deleteUser({ variables: { id } })
+    }}>{title || 'Delete user'}</button>
+  )
+}
+
+export default DeleteUserButton

+ 2 - 2
frontend/components/user/LoginForm.tsx

@@ -23,9 +23,9 @@ const LoginForm = () => {
           variables: values,
           refetchQueries: [{ query: CURRENT_USER }]
         })
-        console.log(data)
+        console.log('LoginForm', data)
       } catch (error) {
-        console.log(error)
+        console.log('LoginForm', error)
       }
     }}>
       <TextInput label='Email' {...inputProps('email')} />

+ 11 - 3
frontend/components/user/LogoutButton.tsx

@@ -1,5 +1,6 @@
-import { useMutation } from 'react-apollo'
+import { useMutation, useQuery } from '@apollo/react-hooks'
 import { USER_LOGOUT, CURRENT_USER } from './graphql'
+import { SyntheticEvent } from 'react'
 
 interface LogoutButtonProps {
   title?: string
@@ -7,10 +8,17 @@ interface LogoutButtonProps {
 
 const LogoutButton = ({ title }: LogoutButtonProps) => {
   const [logout, { loading, error }] = useMutation(USER_LOGOUT)
+  const { refetch } = useQuery(CURRENT_USER)
 
   return (
-    <button disabled={loading} onClick={() => {
-      logout({ refetchQueries: [{ query: CURRENT_USER }] })
+    <button disabled={loading} onClick={async (event: SyntheticEvent) => {
+      try {
+        const data = await logout()
+        console.log('LogoutButton', data)
+        refetch()
+      } catch (error) {
+        console.log('LogoutButton', error)
+      }
     }}>{title || 'Log out'}</button>
   )
 }

+ 3 - 5
frontend/components/user/SignupForm.tsx

@@ -1,6 +1,5 @@
 import { SyntheticEvent } from 'react'
 import { useMutation } from '@apollo/react-hooks'
-import * as Yup from 'yup'
 
 import { useFormHandler, TextInput } from '../form/forms'
 import { USER_SIGNUP } from './graphql'
@@ -8,16 +7,15 @@ import { userValidation } from './validation'
 
 
 const initialValues = {
-  name: 'Tomi',
-  email: 'tomi@cvetic.ch',
+  name: 'Tomi Cvetic',
+  email: 'tomislav.cvetic@u-blox.com',
   password: '1234',
   passwordAgain: '1234'
 }
 
-
 const SignupForm = () => {
 
-  const { inputProps, values } = useFormHandler(initialValues, userValidation.validate)
+  const { inputProps, values } = useFormHandler(initialValues)
   const [userSignup, { loading, error }] = useMutation(USER_SIGNUP)
 
   return (

+ 1 - 1
frontend/components/user/UserDetails.tsx

@@ -4,7 +4,7 @@ import { UserProps } from "./props"
 
 
 const UserDetails = ({ user }: UserProps) => {
-  console.log(user)
+  console.log('UserDetails', user)
   return (
     <>
       <p>{user.id}</p>

+ 4 - 2
frontend/components/user/UserEditForm.tsx

@@ -1,7 +1,9 @@
+import { SyntheticEvent } from "react"
 import { useMutation } from "@apollo/react-hooks"
+
 import { useFormHandler, TextInput } from "../form/forms"
+
 import { CURRENT_USER, USER_EDIT } from "./graphql"
-import { SyntheticEvent } from "react"
 import { UserProps } from "./props"
 import { userValidation } from "./validation"
 
@@ -16,7 +18,7 @@ const initialData = {
 const UserEditForm = ({ user }: UserProps) => {
 
   const [updateUser, userEdit] = useMutation(USER_EDIT)
-  const { inputProps, values } = useFormHandler({ ...initialData, ...user }, userValidation.validate)
+  const { inputProps, values } = useFormHandler({ ...initialData, ...user })
 
   return (
     <form onSubmit={async (event: SyntheticEvent) => {

+ 9 - 2
frontend/components/user/graphql.js → frontend/components/user/graphql.ts

@@ -27,7 +27,7 @@ const USER_LOGOUT = gql`
 `
 
 const CURRENT_USER = gql`
-  query {
+  query CURRENT_USER {
     me {
       id
       email
@@ -54,6 +54,12 @@ const USER_EDIT = gql`
   }
 `
 
+const USER_DELETE = gql`
+  mutation USER_DELETE($id: String!) {
+    userDelete(id: $id)
+  }
+`
+
 export {
   USER_SIGNUP,
   USER_LOGIN,
@@ -61,5 +67,6 @@ export {
   CURRENT_USER,
   USER_REQUEST_PASSWORD,
   USER_RESET_PASSWORD,
-  USER_EDIT
+  USER_EDIT,
+  USER_DELETE
 }

+ 39 - 0
frontend/lib/apollo.js

@@ -0,0 +1,39 @@
+/**
+ * Using next-with-apollo
+ * https://github.com/lfades/next-with-apollo
+ *
+ * Changes:
+ * * Reading endpoint and prodEndpoint from a config file
+ * * Setting request to handle credentials.
+ */
+
+// import { withData } from 'next-apollo'
+// import { HttpLink } from 'apollo-boost'
+// import { ApolloLink } from 'apollo-link'
+// import { onError } from 'apollo-link-error'
+
+import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client'
+
+const client = new ApolloClient({
+  cache: new InMemoryCache(),
+  link: new HttpLink({
+    uri: 'http://localhost:8801/',
+    credentials: 'include'
+  })
+})
+
+// const errorLink = onError(errors => { })
+
+// const httpLink = new HttpLink({
+//   uri: 'http://localhost:8801/',
+//   credentials: 'include'
+// })
+
+// const config = {
+//   link: ApolloLink.from([
+//     errorLink,
+//     httpLink
+//   ])
+// }
+
+export default client

+ 0 - 43
frontend/lib/withApollo.js

@@ -1,43 +0,0 @@
-/**
- * Using next-with-apollo
- * https://github.com/lfades/next-with-apollo
- *
- * Changes:
- * * Reading endpoint and prodEndpoint from a config file
- * * Setting request to handle credentials.
- */
-
-import withApollo from 'next-with-apollo'
-import { ApolloClient } from 'apollo-client'
-import { ApolloLink } from 'apollo-link'
-import { InMemoryCache } from 'apollo-cache-inmemory'
-import { HttpLink } from 'apollo-link-http'
-import { onError } from 'apollo-link-error'
-
-const cache = new InMemoryCache()
-const httpLink = new HttpLink({ uri: 'http://localhost:8801/', credentials: 'include' })
-const errorLink = onError(({ graphQLErrors, networkError, response }) => {
-  console.log('ERRORS', graphQLErrors, networkError)
-  if (graphQLErrors) {
-    graphQLErrors.map(({ message, locations, path }) => {
-      console.log(`[GraphQL error] Message: ${message}, Location: ${locations}, Path: ${path}`)
-    })
-  }
-  if (networkError) {
-    console.log(`[Network error] ${networkError}`)
-  }
-})
-
-const link = ApolloLink.from([
-  errorLink,
-  httpLink
-])
-
-function createClient ({ ctx, headers }) {
-  return new ApolloClient({
-    link,
-    cache
-  })
-}
-
-export default withApollo(createClient)

+ 0 - 3
frontend/next.config.js

@@ -1,3 +0,0 @@
-const withTypescript = require('@zeit/next-typescript')
-
-module.exports = withTypescript()

+ 101 - 264
frontend/package-lock.json

@@ -38,47 +38,47 @@
       "resolved": "https://registry.npmjs.org/@ampproject/toolbox-script-csp/-/toolbox-script-csp-1.1.1.tgz",
       "integrity": "sha512-gACGfsVKinCy/977FSrlVgo6jxTZ0lcTCvCnRlNwvSOcxJVm+jJR3sP7/F43fpak9Gsq/EwFaatfnNMbunPc+w=="
     },
-    "@apollo/react-common": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/@apollo/react-common/-/react-common-3.1.3.tgz",
-      "integrity": "sha512-Q7ZjDOeqjJf/AOGxUMdGxKF+JVClRXrYBGVq+SuVFqANRpd68MxtVV2OjCWavsFAN0eqYnRqRUrl7vtUCiJqeg==",
-      "requires": {
-        "ts-invariant": "^0.4.4",
-        "tslib": "^1.10.0"
-      }
-    },
-    "@apollo/react-components": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/@apollo/react-components/-/react-components-3.1.3.tgz",
-      "integrity": "sha512-H0l2JKDQMz+LkM93QK7j3ThbNXkWQCduN3s3eKxFN3Rdg7rXsrikJWvx2wQ868jmqy0VhwJbS1vYdRLdh114uQ==",
+    "@apollo/client": {
+      "version": "3.0.0-beta.16",
+      "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.0.0-beta.16.tgz",
+      "integrity": "sha512-g5cIMnTwvUCpO4SlBXKXH3vsKI7ie355KC4rZ2Gthon4lZ9GbSf1W8i77ihARElNdybrSuzEVBpenNi+XumVcg==",
       "requires": {
-        "@apollo/react-common": "^3.1.3",
-        "@apollo/react-hooks": "^3.1.3",
-        "prop-types": "^15.7.2",
+        "@types/zen-observable": "^0.8.0",
+        "@wry/equality": "^0.1.9",
+        "fast-json-stable-stringify": "^2.0.0",
+        "graphql-tag": "^2.10.1",
+        "optimism": "^0.11.3",
+        "symbol-observable": "^1.2.0",
         "ts-invariant": "^0.4.4",
-        "tslib": "^1.10.0"
+        "tslib": "^1.10.0",
+        "zen-observable": "^0.8.14"
+      },
+      "dependencies": {
+        "@wry/context": {
+          "version": "0.5.0",
+          "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.5.0.tgz",
+          "integrity": "sha512-yW5XFrWbRvv2/f86+g0YAfko7671SQg7Epn8lYjux4MZmIvtPvK2ts+vG1QAPu2w6GuBioEJknRa7K2LFj2kQw==",
+          "requires": {
+            "tslib": "^1.9.3"
+          }
+        },
+        "optimism": {
+          "version": "0.11.4",
+          "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.11.4.tgz",
+          "integrity": "sha512-a9dQJt/dvrxhkEGK/l1U+T4zJ9OyIOWGnRrbjxy8+mWHVR3C3phmKlRuh2YKkSVjTf8G1kVFVEqL9+s4E77wsg==",
+          "requires": {
+            "@wry/context": "^0.5.0"
+          }
+        }
       }
     },
-    "@apollo/react-hoc": {
+    "@apollo/react-common": {
       "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/@apollo/react-hoc/-/react-hoc-3.1.3.tgz",
-      "integrity": "sha512-oCPma0uBVPTcYTR5sOvtMbpaWll4xDBvYfKr6YkDorUcQVeNzFu1LK1kmQjJP64bKsaziKYji5ibFaeCnVptmA==",
+      "resolved": "https://registry.npmjs.org/@apollo/react-common/-/react-common-3.1.3.tgz",
+      "integrity": "sha512-Q7ZjDOeqjJf/AOGxUMdGxKF+JVClRXrYBGVq+SuVFqANRpd68MxtVV2OjCWavsFAN0eqYnRqRUrl7vtUCiJqeg==",
       "requires": {
-        "@apollo/react-common": "^3.1.3",
-        "@apollo/react-components": "^3.1.3",
-        "hoist-non-react-statics": "^3.3.0",
         "ts-invariant": "^0.4.4",
         "tslib": "^1.10.0"
-      },
-      "dependencies": {
-        "hoist-non-react-statics": {
-          "version": "3.3.0",
-          "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz",
-          "integrity": "sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==",
-          "requires": {
-            "react-is": "^16.7.0"
-          }
-        }
       }
     },
     "@apollo/react-hooks": {
@@ -255,14 +255,6 @@
         }
       }
     },
-    "@babel/helper-annotate-as-pure": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.0.tgz",
-      "integrity": "sha512-k50CQxMlYTYo+GGyUGFwpxKVtxVJi9yh61sXZji3zYHccK9RYliZGSTOgci85T+r+0VFN2nWbGM04PIqwfrpMg==",
-      "requires": {
-        "@babel/types": "^7.7.0"
-      }
-    },
     "@babel/helper-builder-binary-assignment-operator-visitor": {
       "version": "7.7.4",
       "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.4.tgz",
@@ -2197,24 +2189,6 @@
       "resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz",
       "integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw=="
     },
-    "@emotion/is-prop-valid": {
-      "version": "0.8.5",
-      "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.5.tgz",
-      "integrity": "sha512-6ZODuZSFofbxSbcxwsFz+6ioPjb0ISJRRPLZ+WIbjcU2IMU0Io+RGQjjaTgOvNQl007KICBm7zXQaYQEC1r6Bg==",
-      "requires": {
-        "@emotion/memoize": "0.7.3"
-      }
-    },
-    "@emotion/memoize": {
-      "version": "0.7.3",
-      "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.3.tgz",
-      "integrity": "sha512-2Md9mH6mvo+ygq1trTeVp2uzAKwE2P7In0cRpD/M9Q70aH8L+rxMLbb3JCN2JoSWsV2O+DdFjfbbXoMoLBczow=="
-    },
-    "@emotion/unitless": {
-      "version": "0.7.4",
-      "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.4.tgz",
-      "integrity": "sha512-kBa+cDHOR9jpRJ+kcGMsysrls0leukrm68DmFQoMIWQcXdr2cZvyvypWuGYT7U+9kAExUE7+T7r6G3C3A6L8MQ=="
-    },
     "@jest/console": {
       "version": "24.9.0",
       "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz",
@@ -2962,55 +2936,68 @@
       }
     },
     "apollo-boost": {
-      "version": "0.4.4",
-      "resolved": "https://registry.npmjs.org/apollo-boost/-/apollo-boost-0.4.4.tgz",
-      "integrity": "sha512-ASngBvazmp9xNxXfJ2InAzfDwz65o4lswlEPrWoN35scXmCz8Nz4k3CboUXbrcN/G0IExkRf/W7o9Rg0cjEBqg==",
+      "version": "0.4.7",
+      "resolved": "https://registry.npmjs.org/apollo-boost/-/apollo-boost-0.4.7.tgz",
+      "integrity": "sha512-jfc3aqO0vpCV+W662EOG5gq4AH94yIsvSgAUuDvS3o/Z+8Joqn4zGC9CgLCDHusK30mFgtsEgwEe0pZoedohsQ==",
       "requires": {
-        "apollo-cache": "^1.3.2",
-        "apollo-cache-inmemory": "^1.6.3",
-        "apollo-client": "^2.6.4",
+        "apollo-cache": "^1.3.4",
+        "apollo-cache-inmemory": "^1.6.5",
+        "apollo-client": "^2.6.7",
         "apollo-link": "^1.0.6",
         "apollo-link-error": "^1.0.3",
         "apollo-link-http": "^1.3.1",
         "graphql-tag": "^2.4.2",
         "ts-invariant": "^0.4.0",
-        "tslib": "^1.9.3"
-      }
-    },
-    "apollo-cache": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/apollo-cache/-/apollo-cache-1.3.2.tgz",
-      "integrity": "sha512-+KA685AV5ETEJfjZuviRTEImGA11uNBp/MJGnaCvkgr+BYRrGLruVKBv6WvyFod27WEB2sp7SsG8cNBKANhGLg==",
-      "requires": {
-        "apollo-utilities": "^1.3.2",
-        "tslib": "^1.9.3"
-      }
-    },
-    "apollo-cache-inmemory": {
-      "version": "1.6.3",
-      "resolved": "https://registry.npmjs.org/apollo-cache-inmemory/-/apollo-cache-inmemory-1.6.3.tgz",
-      "integrity": "sha512-S4B/zQNSuYc0M/1Wq8dJDTIO9yRgU0ZwDGnmlqxGGmFombOZb9mLjylewSfQKmjNpciZ7iUIBbJ0mHlPJTzdXg==",
-      "requires": {
-        "apollo-cache": "^1.3.2",
-        "apollo-utilities": "^1.3.2",
-        "optimism": "^0.10.0",
-        "ts-invariant": "^0.4.0",
-        "tslib": "^1.9.3"
-      }
-    },
-    "apollo-client": {
-      "version": "2.6.4",
-      "resolved": "https://registry.npmjs.org/apollo-client/-/apollo-client-2.6.4.tgz",
-      "integrity": "sha512-oWOwEOxQ9neHHVZrQhHDbI6bIibp9SHgxaLRVPoGvOFy7OH5XUykZE7hBQAVxq99tQjBzgytaZffQkeWo1B4VQ==",
-      "requires": {
-        "@types/zen-observable": "^0.8.0",
-        "apollo-cache": "1.3.2",
-        "apollo-link": "^1.0.0",
-        "apollo-utilities": "1.3.2",
-        "symbol-observable": "^1.0.2",
-        "ts-invariant": "^0.4.0",
-        "tslib": "^1.9.3",
-        "zen-observable": "^0.8.0"
+        "tslib": "^1.10.0"
+      },
+      "dependencies": {
+        "apollo-cache": {
+          "version": "1.3.4",
+          "resolved": "https://registry.npmjs.org/apollo-cache/-/apollo-cache-1.3.4.tgz",
+          "integrity": "sha512-7X5aGbqaOWYG+SSkCzJNHTz2ZKDcyRwtmvW4mGVLRqdQs+HxfXS4dUS2CcwrAj449se6tZ6NLUMnjko4KMt3KA==",
+          "requires": {
+            "apollo-utilities": "^1.3.3",
+            "tslib": "^1.10.0"
+          }
+        },
+        "apollo-cache-inmemory": {
+          "version": "1.6.5",
+          "resolved": "https://registry.npmjs.org/apollo-cache-inmemory/-/apollo-cache-inmemory-1.6.5.tgz",
+          "integrity": "sha512-koB76JUDJaycfejHmrXBbWIN9pRKM0Z9CJGQcBzIOtmte1JhEBSuzsOUu7NQgiXKYI4iGoMREcnaWffsosZynA==",
+          "requires": {
+            "apollo-cache": "^1.3.4",
+            "apollo-utilities": "^1.3.3",
+            "optimism": "^0.10.0",
+            "ts-invariant": "^0.4.0",
+            "tslib": "^1.10.0"
+          }
+        },
+        "apollo-client": {
+          "version": "2.6.8",
+          "resolved": "https://registry.npmjs.org/apollo-client/-/apollo-client-2.6.8.tgz",
+          "integrity": "sha512-0zvJtAcONiozpa5z5zgou83iEKkBaXhhSSXJebFHRXs100SecDojyUWKjwTtBPn9HbM6o5xrvC5mo9VQ5fgAjw==",
+          "requires": {
+            "@types/zen-observable": "^0.8.0",
+            "apollo-cache": "1.3.4",
+            "apollo-link": "^1.0.0",
+            "apollo-utilities": "1.3.3",
+            "symbol-observable": "^1.0.2",
+            "ts-invariant": "^0.4.0",
+            "tslib": "^1.10.0",
+            "zen-observable": "^0.8.0"
+          }
+        },
+        "apollo-utilities": {
+          "version": "1.3.3",
+          "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.3.3.tgz",
+          "integrity": "sha512-F14aX2R/fKNYMvhuP2t9GD9fggID7zp5I96MF5QeKYWDWTrkRdHRp4+SVfXUVN+cXOaB/IebfvRtzPf25CM0zw==",
+          "requires": {
+            "@wry/equality": "^0.1.2",
+            "fast-json-stable-stringify": "^2.0.0",
+            "ts-invariant": "^0.4.0",
+            "tslib": "^1.10.0"
+          }
+        }
       }
     },
     "apollo-link": {
@@ -3600,17 +3587,6 @@
         "@types/babel__traverse": "^7.0.6"
       }
     },
-    "babel-plugin-styled-components": {
-      "version": "1.10.6",
-      "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.10.6.tgz",
-      "integrity": "sha512-gyQj/Zf1kQti66100PhrCRjI5ldjaze9O0M3emXRPAN80Zsf8+e1thpTpaXJXVHXtaM4/+dJEgZHyS9Its+8SA==",
-      "requires": {
-        "@babel/helper-annotate-as-pure": "^7.0.0",
-        "@babel/helper-module-imports": "^7.0.0",
-        "babel-plugin-syntax-jsx": "^6.18.0",
-        "lodash": "^4.17.11"
-      }
-    },
     "babel-plugin-syntax-jsx": {
       "version": "6.18.0",
       "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
@@ -4011,11 +3987,6 @@
       "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
       "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
     },
-    "camelize": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz",
-      "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
-    },
     "caniuse-lite": {
       "version": "1.0.30001008",
       "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001008.tgz",
@@ -4542,11 +4513,6 @@
         "postcss": "^7.0.5"
       }
     },
-    "css-color-keywords": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
-      "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU="
-    },
     "css-has-pseudo": {
       "version": "0.10.0",
       "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz",
@@ -4612,23 +4578,6 @@
         "nth-check": "~1.0.1"
       }
     },
-    "css-to-react-native": {
-      "version": "2.3.2",
-      "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-2.3.2.tgz",
-      "integrity": "sha512-VOFaeZA053BqvvvqIA8c9n0+9vFppVBAHCp6JgFTtTMU3Mzi+XnelJ9XC9ul3BqFzZyQ5N+H0SnwsWT2Ebchxw==",
-      "requires": {
-        "camelize": "^1.0.0",
-        "css-color-keywords": "^1.0.0",
-        "postcss-value-parser": "^3.3.0"
-      },
-      "dependencies": {
-        "postcss-value-parser": {
-          "version": "3.3.1",
-          "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
-          "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="
-        }
-      }
-    },
     "css-what": {
       "version": "2.1.3",
       "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
@@ -4750,11 +4699,6 @@
       "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
       "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ="
     },
-    "deepmerge": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz",
-      "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA=="
-    },
     "defaults": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
@@ -6159,31 +6103,6 @@
         "mime-types": "^2.1.12"
       }
     },
-    "formik": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/formik/-/formik-2.0.6.tgz",
-      "integrity": "sha512-x2fC80v8AIrGgpxWrLqKaK9hdV8WX4OSLK+Fr5lclqExA59NCuxdB3WiuxJQc9/g043BmfTIuaILrV9Wq0MPVw==",
-      "requires": {
-        "deepmerge": "^2.1.1",
-        "hoist-non-react-statics": "^3.3.0",
-        "lodash": "^4.17.14",
-        "lodash-es": "^4.17.14",
-        "react-fast-compare": "^2.0.1",
-        "scheduler": "^0.17.0",
-        "tiny-warning": "^1.0.2",
-        "tslib": "^1.10.0"
-      },
-      "dependencies": {
-        "hoist-non-react-statics": {
-          "version": "3.3.1",
-          "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
-          "integrity": "sha512-wbg3bpgA/ZqWrZuMOeJi8+SKMhr7X9TesL/rXMjTzh0p0JUBo3II8DHboYbuIXWRlttrUFxwcu/5kygrCw8fJw==",
-          "requires": {
-            "react-is": "^16.7.0"
-          }
-        }
-      }
-    },
     "fragment-cache": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
@@ -7014,11 +6933,6 @@
         "minimalistic-crypto-utils": "^1.0.1"
       }
     },
-    "hoist-non-react-statics": {
-      "version": "2.5.5",
-      "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
-      "integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw=="
-    },
     "hosted-git-info": {
       "version": "2.8.5",
       "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz",
@@ -7533,11 +7447,6 @@
       "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
       "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
     },
-    "is-what": {
-      "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.3.1.tgz",
-      "integrity": "sha512-seFn10yAXy+yJlTRO+8VfiafC+0QJanGLMPTBWLrJm/QPauuchy0UXh8B6H5o9VA8BAzk0iYievt6mNp6gfaqA=="
-    },
     "is-windows": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
@@ -8365,11 +8274,6 @@
       "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
       "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
     },
-    "lodash-es": {
-      "version": "4.17.15",
-      "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.15.tgz",
-      "integrity": "sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ=="
-    },
     "lodash._reinterpolate": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
@@ -8485,11 +8389,6 @@
         "safe-buffer": "^5.1.2"
       }
     },
-    "memoize-one": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz",
-      "integrity": "sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA=="
-    },
     "memory-fs": {
       "version": "0.4.1",
       "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
@@ -8499,14 +8398,6 @@
         "readable-stream": "^2.0.1"
       }
     },
-    "merge-anything": {
-      "version": "2.4.1",
-      "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-2.4.1.tgz",
-      "integrity": "sha512-dYOIAl9GFCJNctSIHWOj9OJtarCjsD16P8ObCl6oxrujAG+kOvlwJuOD9/O9iYZ9aTi1RGpGTG9q9etIvuUikQ==",
-      "requires": {
-        "is-what": "^3.3.1"
-      }
-    },
     "merge-stream": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -8932,6 +8823,18 @@
         }
       }
     },
+    "next-apollo": {
+      "version": "3.1.10",
+      "resolved": "https://registry.npmjs.org/next-apollo/-/next-apollo-3.1.10.tgz",
+      "integrity": "sha512-VX64IW7h6Rdg+Ma0y8ryAIz7IfyLaz6Nd4VITuhfXFZ3nj51blcjRR6kc4E945SPk2WdrIMlLRZubgPRAgh9Ug==",
+      "requires": {
+        "@babel/runtime": "^7.4.5",
+        "isomorphic-unfetch": "^3.0.0",
+        "prop-types": "15.7.2",
+        "prop-types-exact": "1.2.0",
+        "url": "0.11.0"
+      }
+    },
     "next-link": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/next-link/-/next-link-2.0.0.tgz",
@@ -8940,15 +8843,6 @@
         "on-headers": "^1.0.1"
       }
     },
-    "next-with-apollo": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/next-with-apollo/-/next-with-apollo-4.3.0.tgz",
-      "integrity": "sha512-sponVO+ii44K1Ua2mMeDLTX3BEdHPwQI2R6xhJB7qQG8JUnU1kaZSmrYonQFHcDSf0vEcO87vecZpcMUye8MtA==",
-      "requires": {
-        "@apollo/react-ssr": "^3.0.1",
-        "isomorphic-unfetch": "^3.0.0"
-      }
-    },
     "nice-try": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
@@ -10467,33 +10361,6 @@
         "prop-types": "^15.6.2"
       }
     },
-    "react-adopt": {
-      "version": "0.6.0",
-      "resolved": "https://registry.npmjs.org/react-adopt/-/react-adopt-0.6.0.tgz",
-      "integrity": "sha1-5f+QOmVdMIIhf4K8nVAzpLZPr60=",
-      "requires": {
-        "hoist-non-react-statics": "^2.5.0",
-        "react": "^16.3.2",
-        "react-display-name": "^0.2.4"
-      }
-    },
-    "react-apollo": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/react-apollo/-/react-apollo-3.1.3.tgz",
-      "integrity": "sha512-orCZNoAkgveaK5b75y7fw1MSqSHOU/Wuu9rRFOGmRQBSQVZjvV4DI+hj604rHmuN9+WDABxb5W48wTa0F/xNZQ==",
-      "requires": {
-        "@apollo/react-common": "^3.1.3",
-        "@apollo/react-components": "^3.1.3",
-        "@apollo/react-hoc": "^3.1.3",
-        "@apollo/react-hooks": "^3.1.3",
-        "@apollo/react-ssr": "^3.1.3"
-      }
-    },
-    "react-display-name": {
-      "version": "0.2.4",
-      "resolved": "https://registry.npmjs.org/react-display-name/-/react-display-name-0.2.4.tgz",
-      "integrity": "sha512-zvU6iouW+SWwHTyThwxGICjJYCMZFk/6r/+jmOdC7ntQoPlS/Pqb81MkxaMf2bHTSq9TN3K3zX2/ayMW/jCtyA=="
-    },
     "react-dom": {
       "version": "16.11.0",
       "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.11.0.tgz",
@@ -10510,11 +10377,6 @@
       "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-5.1.6.tgz",
       "integrity": "sha512-X1Y+0jR47ImDVr54Ab6V9eGk0Hnu7fVWGeHQSOXHf/C2pF9c6uy3gef8QUeuUiWlNb0i08InPSE5a/KJzNzw1Q=="
     },
-    "react-fast-compare": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz",
-      "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw=="
-    },
     "react-is": {
       "version": "16.8.6",
       "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz",
@@ -11598,26 +11460,6 @@
         "schema-utils": "^2.0.1"
       }
     },
-    "styled-components": {
-      "version": "4.4.1",
-      "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-4.4.1.tgz",
-      "integrity": "sha512-RNqj14kYzw++6Sr38n7197xG33ipEOktGElty4I70IKzQF1jzaD1U4xQ+Ny/i03UUhHlC5NWEO+d8olRCDji6g==",
-      "requires": {
-        "@babel/helper-module-imports": "^7.0.0",
-        "@babel/traverse": "^7.0.0",
-        "@emotion/is-prop-valid": "^0.8.1",
-        "@emotion/unitless": "^0.7.0",
-        "babel-plugin-styled-components": ">= 1",
-        "css-to-react-native": "^2.2.2",
-        "memoize-one": "^5.0.0",
-        "merge-anything": "^2.2.4",
-        "prop-types": "^15.5.4",
-        "react-is": "^16.6.0",
-        "stylis": "^3.5.0",
-        "stylis-rule-sheet": "^0.0.10",
-        "supports-color": "^5.5.0"
-      }
-    },
     "styled-jsx": {
       "version": "3.2.2",
       "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-3.2.2.tgz",
@@ -11987,11 +11829,6 @@
         "setimmediate": "^1.0.4"
       }
     },
-    "tiny-warning": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
-      "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
-    },
     "tmp": {
       "version": "0.0.33",
       "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",

+ 6 - 11
frontend/package.json

@@ -11,28 +11,23 @@
     "type-check": "tsc"
   },
   "dependencies": {
-    "apollo-boost": "^0.4.4",
-    "apollo-cache-inmemory": "^1.6.3",
-    "apollo-client": "^2.6.4",
+    "@apollo/client": "^3.0.0-beta.16",
+    "@apollo/react-hooks": "^3.1.3",
+    "@apollo/react-ssr": "^3.1.3",
+    "apollo-boost": "0.4.7",
     "apollo-link": "^1.2.13",
     "apollo-link-error": "^1.1.12",
-    "apollo-link-http": "^1.5.16",
     "dotenv": "^8.2.0",
-    "formik": "^2.0.6",
     "fuse.js": "3.4.5",
     "graphql": "^14.5.8",
-    "graphql-tag": "^2.10.1",
     "next": "9.1.2",
+    "next-apollo": "^3.1.10",
     "next-link": "^2.0.0",
-    "next-with-apollo": "^4.3.0",
     "normalize.css": "^8.0.1",
     "nprogress": "^0.2.0",
-    "react": "16.11.0",
-    "react-adopt": "^0.6.0",
-    "react-apollo": "^3.1.3",
+    "react": "^16.11.0",
     "react-dom": "16.11.0",
     "standard": "^14.3.1",
-    "styled-components": "^4.4.1",
     "yup": "^0.27.0"
   },
   "devDependencies": {

+ 5 - 5
frontend/pages/_app.js

@@ -1,6 +1,6 @@
 import App from 'next/app'
-import { ApolloProvider } from 'react-apollo'
-import withApollo from '../lib/withApollo'
+import client from '../lib/apollo'
+import { ApolloProvider } from '@apollo/client'
 import Page from '../components/page'
 
 /**
@@ -27,10 +27,10 @@ class MyApp extends App {
   }
 
   render () {
-    const { Component, apollo, pageProps } = this.props
+    const { Component, pageProps } = this.props
 
     return (
-      <ApolloProvider client={apollo}>
+      <ApolloProvider client={client}>
         <Page>
           <Component {...pageProps} />
         </Page>
@@ -39,4 +39,4 @@ class MyApp extends App {
   }
 }
 
-export default withApollo(MyApp)
+export default MyApp

+ 40 - 45
frontend/pages/index.js

@@ -1,4 +1,4 @@
-import { Query } from 'react-apollo'
+import { useQuery } from '@apollo/react-hooks'
 import Link from 'next/link'
 
 import Training from '../components/training'
@@ -7,50 +7,45 @@ import { TRAININGS } from '../lib/graphql'
 
 console.log(initialData)
 
-const Home = () => (
-  <>
-    <section>
-      <h1>Stay in Shape with u-fit</h1>
-      <p>u-fit is a high intensity interval training offered by u-blox.</p>
-      <aside>
-        <div id='trainingTime'>
-          <span className='caption'>When</span>
-          <span className='data'>Tuesdays, 11:45-12:30</span>
-        </div>
-        <div id='trainingEquipment'>
-          <span className='caption'>Equipment</span>
-          <span className='data'>Towel, water, optional: yoga mat</span>
-        </div>
-      </aside>
-    </section>
+const Home = () => {
+  const { data, error, loading } = useQuery(TRAININGS)
 
-    <section id='nextTraining'>
-      <Query query={TRAININGS}>
-        {({ data, error, loading }) => {
-          if (error) return <p>Error {error.message}</p>
-          if (loading) return <p>Loading...</p>
-          if (data.trainings.length) {
-            console.log(data)
-            return (
-              <>
-                <Training
-                  {...{
-                    ...data.trainings[data.trainings.length - 1],
-                    title: `Your Next Training: ${
-                      data.trainings[data.trainings.length - 1].title
-                    }`
-                  }}
-                />
-              </>
-            )
-          } else return <p>Nothing found...</p>
-        }}
-      </Query>
-      <Link href={{ pathname: '/training' }}>
-        <a>create training...</a>
-      </Link>
-    </section>
-  </>
-)
+  return (
+    <>
+      <section>
+        <h1>Stay in Shape with u-fit</h1>
+        <p>u-fit is a high intensity interval training offered by u-blox.</p>
+        <aside>
+          <div id='trainingTime'>
+            <span className='caption'>When</span>
+            <span className='data'>Tuesdays, 11:45-12:30</span>
+          </div>
+          <div id='trainingEquipment'>
+            <span className='caption'>Equipment</span>
+            <span className='data'>Towel, water, optional: yoga mat</span>
+          </div>
+        </aside>
+      </section>
+
+      <section id='nextTraining'>
+        {error && (<p>Error {error.message}</p>)}
+        {loading && (<p>Loading...</p>)}
+        {data ? (
+          <Training
+            {...{
+              ...data.trainings[data.trainings.length - 1],
+              title: `Your Next Training: ${
+                data.trainings[data.trainings.length - 1].title
+                }`
+            }}
+          />
+        ) : (<p>Nothing found...</p>)}
+        <Link href={{ pathname: '/training' }}>
+          <a>create training...</a>
+        </Link>
+      </section>
+    </>
+  )
+}
 
 export default Home

+ 27 - 11
frontend/pages/user.tsx

@@ -1,4 +1,6 @@
-import { useQuery } from 'react-apollo'
+import { useQuery } from '@apollo/react-hooks'
+import { withRouter } from 'next/router'
+
 import SignupForm from '../components/user/SignupForm'
 import LoginForm from '../components/user/LoginForm'
 import LogoutButton from '../components/user/LogoutButton'
@@ -6,26 +8,40 @@ import RequestPassword from '../components/user/RequestPassword'
 import ResetPassword from '../components/user/ResetPassword'
 import UserEditForm from '../components/user/UserEditForm'
 import UserDetails from '../components/user/UserDetails'
+import DeleteUserButton from '../components/user/DeleteUserButton'
+
 import { CURRENT_USER } from '../components/user/graphql'
 
+
 const UserPage = () => {
+  console.log('UserPage, entering')
   const { data, loading, error } = useQuery(CURRENT_USER)
+  console.log('UserPage', data, loading, error && error.message)
 
   return (
     <>
+      {error && <LoginForm />}
+      {data && <LogoutButton />}
+      <p>{error && error.message}</p>
+    </>
+  )
+
+  /*return (
+    <>
+      {data && data.me.name}
+      {error && error.message}
+      {loading && 'Loading'}
       <SignupForm />
-      <LoginForm />
-      <LogoutButton />
+      {!data && <LoginForm />}
+      {data && <LogoutButton />}
       <RequestPassword />
       <ResetPassword />
-      {data && (
-        <>
-          <UserEditForm user={data.me} />
-          <UserDetails user={data.me} />
-        </>
-      )}
+      {data && <UserEditForm user={data.me} />}
+      {data && <UserDetails user={data.me} />}
+      {data && <DeleteUserButton user={data.me} />}
+      {<p>{error && error.message}</p>}
     </>
-  )
+  )*/
 }
 
-export default UserPage
+export default withRouter(UserPage)

+ 0 - 3
package-lock.json

@@ -1,3 +0,0 @@
-{
-  "lockfileVersion": 1
-}