Browse Source

Implement me query to fetch user data on app load

Andrew Swistak 6 years ago
parent
commit
397ed16631

+ 11 - 0
app/graphql/resolvers/user/me_resolver.rb

@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Resolvers
+  class User::MeResolver < BaseResolver
+    description 'Returns information about the current logged in user'
+
+    def resolve(*)
+      context[:current_user]
+    end
+  end
+end

+ 6 - 0
app/graphql/types/query_type.rb

@@ -10,6 +10,12 @@ module Types
           resolver: Resolvers::PokemonResolver.single,
           description: 'Fetches exactly zero or one pokemon'
 
+    field :me,
+          Types::UserType,
+          null: true,
+          resolver: Resolvers::User::MeResolver,
+          description: 'Returns information about the current logged in user'
+
     field :many_pokemon,
           [Types::PokemonType],
           null: false,

+ 0 - 2
app/graphql/types/user_type.rb

@@ -10,7 +10,5 @@ module Types
     field :iid, GraphQL::ID_TYPE, null: false, method: :id
     field :username, GraphQL::STRING_TYPE, null: true
     field :email, GraphQL::STRING_TYPE, null: true
-    field :created_at, Types::TimeType, null: true
-    field :updated_at, Types::TimeType, null: true
   end
 end

+ 6 - 9
app/javascript/src/components/layout/ApplicationLayout.tsx

@@ -1,7 +1,9 @@
 import React from 'react';
-import {Navbar, Nav, Form, FormControl, Button} from 'react-bootstrap';
+import {Navbar, Nav} from 'react-bootstrap';
 import {Link} from 'found';
 
+import {UserContext} from '../../context/User';
+
 interface Props {
   children?: React.ReactNode;
 }
@@ -21,14 +23,9 @@ function ApplicationLayout({children}: Props): React.ReactElement {
                 View Pokemon
               </Nav.Link>
             </Nav>
-            <Form inline>
-              <FormControl
-                className='mr-sm-2'
-                placeholder='Search'
-                type='text'
-              />
-              <Button variant='primary'>Search</Button>
-            </Form>
+            <UserContext.Consumer>
+              {user => user && user.email}
+            </UserContext.Consumer>
           </Navbar.Collapse>
         </Navbar>
       </nav>

+ 35 - 0
app/javascript/src/context/User.tsx

@@ -0,0 +1,35 @@
+import React, {useState, useEffect} from 'react';
+import {fetchQuery, graphql} from 'react-relay';
+
+import graphqlEnvironment from '../graphqlEnvironment';
+import {User_QueryResponse as UserResponse} from './__generated__/User_Query.graphql';
+
+export type User = UserResponse['me'];
+export const UserContext = React.createContext<User | null>(null);
+
+const query = graphql`
+  query User_Query {
+    me {
+      iid
+      username
+      email
+    }
+  }
+`;
+
+interface Props {
+  children: React.ReactNode;
+}
+
+export const UserProvider: React.FC<Props> = ({children}) => {
+  const [user, setUser] = useState(null);
+
+  useEffect(() => {
+    (async () => {
+      const response = await fetchQuery(graphqlEnvironment, query, {}) as UserResponse;
+      setUser(response.me);
+    })();
+  }, []);
+
+  return <UserContext.Provider value={user}>{children}</UserContext.Provider>;
+};

+ 115 - 0
app/javascript/src/context/__generated__/User_Query.graphql.ts

@@ -0,0 +1,115 @@
+/* tslint:disable */
+
+import { ConcreteRequest } from "relay-runtime";
+export type User_QueryVariables = {};
+export type User_QueryResponse = {
+    readonly me: {
+        readonly iid: string;
+        readonly username: string | null;
+        readonly email: string | null;
+    } | null;
+};
+export type User_Query = {
+    readonly response: User_QueryResponse;
+    readonly variables: User_QueryVariables;
+};
+
+
+
+/*
+query User_Query {
+  me {
+    iid
+    username
+    email
+    id
+  }
+}
+*/
+
+const node: ConcreteRequest = (function(){
+var v0 = {
+  "kind": "ScalarField",
+  "alias": null,
+  "name": "iid",
+  "args": null,
+  "storageKey": null
+},
+v1 = {
+  "kind": "ScalarField",
+  "alias": null,
+  "name": "username",
+  "args": null,
+  "storageKey": null
+},
+v2 = {
+  "kind": "ScalarField",
+  "alias": null,
+  "name": "email",
+  "args": null,
+  "storageKey": null
+};
+return {
+  "kind": "Request",
+  "fragment": {
+    "kind": "Fragment",
+    "name": "User_Query",
+    "type": "Query",
+    "metadata": null,
+    "argumentDefinitions": [],
+    "selections": [
+      {
+        "kind": "LinkedField",
+        "alias": null,
+        "name": "me",
+        "storageKey": null,
+        "args": null,
+        "concreteType": "User",
+        "plural": false,
+        "selections": [
+          (v0/*: any*/),
+          (v1/*: any*/),
+          (v2/*: any*/)
+        ]
+      }
+    ]
+  },
+  "operation": {
+    "kind": "Operation",
+    "name": "User_Query",
+    "argumentDefinitions": [],
+    "selections": [
+      {
+        "kind": "LinkedField",
+        "alias": null,
+        "name": "me",
+        "storageKey": null,
+        "args": null,
+        "concreteType": "User",
+        "plural": false,
+        "selections": [
+          (v0/*: any*/),
+          (v1/*: any*/),
+          (v2/*: any*/),
+          {
+            "kind": "ScalarField",
+            "alias": null,
+            "name": "id",
+            "args": null,
+            "storageKey": null
+          }
+        ]
+      }
+    ]
+  },
+  "params": {
+    "operationKind": "query",
+    "name": "User_Query",
+    "id": null,
+    "text": "query User_Query {\n  me {\n    iid\n    username\n    email\n    id\n  }\n}\n",
+    "metadata": {}
+  }
+};
+})();
+(node as any).hash = 'a2d5191273ecf6cdfbab27d81693a978';
+export default node;

+ 6 - 1
app/javascript/src/index.tsx

@@ -16,6 +16,7 @@ import PokemonIndex from './components/pages/pokemon/Index';
 import PokemonCreate from './components/pages/pokemon/Create';
 import Signup from './components/pages/Signup';
 import Login from './components/pages/Login';
+import {UserProvider} from './context/User';
 
 function App(): React.ReactElement {
   const routeConfig = makeRouteConfig(
@@ -53,7 +54,11 @@ function App(): React.ReactElement {
     render: createRender({}),
   });
 
-  return <Router resolver={new Resolver(graphqlEnvironment)} />;
+  return (
+    <UserProvider>
+      <Router resolver={new Resolver(graphqlEnvironment)} />
+    </UserProvider>
+  );
 }
 
 export default hot(App);

+ 5 - 2
db/schema.graphql

@@ -133,6 +133,11 @@ type Query {
   """
   manyPokemon(id: String, ids: [String!], iid: ID, iids: [ID!], nickname: String, nicknames: [String!], pokedexNumber: Int, pokedexNumbers: [Int!]): [Pokemon!]!
 
+  """
+  Returns information about the current logged in user
+  """
+  me: User
+
   """
   Fetches an object given its ID.
   """
@@ -224,10 +229,8 @@ type UploadPokemonPayload {
 Returns a singular user
 """
 type User implements Node {
-  createdAt: Time
   email: String
   id: ID!
   iid: ID!
-  updatedAt: Time
   username: String
 }