diff --git a/components/App.js b/components/App.js index 605efde..f8220d8 100644 --- a/components/App.js +++ b/components/App.js @@ -1,56 +1,29 @@ import { QueryRenderer, graphql } from 'react-relay'; -import { - Environment, - Network, - RecordSource, - Store, - RecordSourceInspector, -} from 'relay-runtime'; +import environment from './Environment'; import LocationsList from './LocationsList'; - -async function fetchQuery(operation, variables) { - const response = await fetch( - 'https://mh67geuwe5.execute-api.eu-west-1.amazonaws.com/dev/', - { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - query: operation.text, - variables, - }), - }, - ); - - return response.json(); -} - -const source = new RecordSource(); -const inspector = new RecordSourceInspector(source); -const modernEnvironment = new Environment({ - network: Network.create(fetchQuery), - store: new Store(source), -}); +import Login from './Login'; export default () => - { - if (props) { - return ( -
- -
- ); - } else { - return
Loading
; - } - }} - />; +
+ { + if (props) { + return ( +
+ +
+ ); + } else { + return
Loading
; + } + }} + /> + +
; diff --git a/components/City.js b/components/City.js index d88f89d..b1710a0 100644 --- a/components/City.js +++ b/components/City.js @@ -21,5 +21,5 @@ export default createFragmentContainer( name slug } - `, + ` ); diff --git a/components/Environment.js b/components/Environment.js new file mode 100644 index 0000000..341e121 --- /dev/null +++ b/components/Environment.js @@ -0,0 +1,42 @@ +import { + Environment, + Network, + RecordSource, + Store, + RecordSourceInspector +} from 'relay-runtime'; + +import Location from './Location'; +import Login from './Login'; + +async function fetchQuery(operation, variables) { + const token = localStorage ? localStorage.getItem('token') : ''; + + const response = await fetch( + 'https://mh67geuwe5.execute-api.eu-west-1.amazonaws.com/dev/', + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: token + }, + body: JSON.stringify({ + query: operation.text, + variables + }) + } + ); + + return response.json(); +} + +const source = new RecordSource(); + +export const inspector = new RecordSourceInspector(source); + +const environment = new Environment({ + network: Network.create(fetchQuery), + store: new Store(source) +}); + +export default environment; diff --git a/components/Location.js b/components/Location.js index b96f489..e29381d 100644 --- a/components/Location.js +++ b/components/Location.js @@ -20,5 +20,5 @@ export default createFragmentContainer( ...City } } - `, + ` ); diff --git a/components/LocationsList.js b/components/LocationsList.js index 3ace27f..aae5b73 100644 --- a/components/LocationsList.js +++ b/components/LocationsList.js @@ -1,4 +1,4 @@ -import { createFragmentContainer, graphql } from 'react-relay'; +import { createFragmentContainer, queryRenderer, graphql } from 'react-relay'; import Location from './Location'; const LocationsList = ({ data }) => { @@ -7,7 +7,7 @@ const LocationsList = ({ data }) => { Loaded: {data.allLocations.edges.length}
    {data.allLocations.edges.map(({ node, cursor }) => - , + )}
@@ -27,5 +27,5 @@ export default createFragmentContainer( } } } - `, + ` ); diff --git a/components/Login.js b/components/Login.js new file mode 100644 index 0000000..99e372e --- /dev/null +++ b/components/Login.js @@ -0,0 +1,29 @@ +import React, { Component } from 'react'; +import environment from './Environment'; +import { QueryRenderer, graphql } from 'react-relay'; +import UserInfo from './UserInfo'; +import LoginButton from './LoginButton'; + +export default () => + { + if (error) { + return ( +
+ {error.message} +
+ ); + } else if (props && props.currentUser) { + return ; + } + return ; + }} + />; diff --git a/components/LoginButton.js b/components/LoginButton.js new file mode 100644 index 0000000..7a97a0b --- /dev/null +++ b/components/LoginButton.js @@ -0,0 +1,14 @@ +import React, { Component } from 'react'; +import LoginMutation from './mutations/LoginMutation'; +import environment from './Environment'; + +class LoginButton extends Component { + handleLogin = () => { + LoginMutation.commit(environment, 'kiwicomtester@gmail.com', 'bflmpsvz'); + }; + render() { + return ; + } +} + +export default LoginButton; diff --git a/components/UserInfo.js b/components/UserInfo.js new file mode 100644 index 0000000..9fff7ce --- /dev/null +++ b/components/UserInfo.js @@ -0,0 +1,23 @@ +import React, { Component } from 'react'; +import { createFragmentContainer, graphql } from 'react-relay'; + +class UserInfo extends Component { + render() { + return ( +
+ Logged in as: {this.props.user.lastName} +
+ ); + } +} + +export default createFragmentContainer( + UserInfo, + graphql` + fragment UserInfo_user on Identity { + id + email + lastName + } + ` +); diff --git a/components/__generated__/LoginQuery.graphql.js b/components/__generated__/LoginQuery.graphql.js new file mode 100644 index 0000000..1a92a72 --- /dev/null +++ b/components/__generated__/LoginQuery.graphql.js @@ -0,0 +1,106 @@ +/** + * @flow + * @relayHash 63bde72e7d56f115a8ecd9a8443829fa + */ + +/* eslint-disable */ + +'use strict'; + +/*:: +import type {ConcreteBatch} from 'relay-runtime'; +export type LoginQueryResponse = {| + +currentUser: ?{| |}; +|}; +*/ + + +/* +query LoginQuery { + currentUser { + ...UserInfo_user + id + } +} + +fragment UserInfo_user on Identity { + id + email + lastName +} +*/ + +const batch /*: ConcreteBatch*/ = { + "fragment": { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "LoginQuery", + "selections": [ + { + "kind": "LinkedField", + "alias": null, + "args": null, + "concreteType": "Identity", + "name": "currentUser", + "plural": false, + "selections": [ + { + "kind": "FragmentSpread", + "name": "UserInfo_user", + "args": null + } + ], + "storageKey": null + } + ], + "type": "RootQuery" + }, + "id": null, + "kind": "Batch", + "metadata": {}, + "name": "LoginQuery", + "query": { + "argumentDefinitions": [], + "kind": "Root", + "name": "LoginQuery", + "operation": "query", + "selections": [ + { + "kind": "LinkedField", + "alias": null, + "args": null, + "concreteType": "Identity", + "name": "currentUser", + "plural": false, + "selections": [ + { + "kind": "ScalarField", + "alias": null, + "args": null, + "name": "id", + "storageKey": null + }, + { + "kind": "ScalarField", + "alias": null, + "args": null, + "name": "email", + "storageKey": null + }, + { + "kind": "ScalarField", + "alias": null, + "args": null, + "name": "lastName", + "storageKey": null + } + ], + "storageKey": null + } + ] + }, + "text": "query LoginQuery {\n currentUser {\n ...UserInfo_user\n id\n }\n}\n\nfragment UserInfo_user on Identity {\n id\n email\n lastName\n}\n" +}; + +module.exports = batch; diff --git a/components/__generated__/UserInfo_user.graphql.js b/components/__generated__/UserInfo_user.graphql.js new file mode 100644 index 0000000..8a57eb5 --- /dev/null +++ b/components/__generated__/UserInfo_user.graphql.js @@ -0,0 +1,50 @@ +/** + * @flow + */ + +/* eslint-disable */ + +'use strict'; + +/*:: +import type {ConcreteFragment} from 'relay-runtime'; +export type UserInfo_user = {| + +id: ?string; + +email: ?string; + +lastName: ?string; +|}; +*/ + + +const fragment /*: ConcreteFragment*/ = { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "UserInfo_user", + "selections": [ + { + "kind": "ScalarField", + "alias": null, + "args": null, + "name": "id", + "storageKey": null + }, + { + "kind": "ScalarField", + "alias": null, + "args": null, + "name": "email", + "storageKey": null + }, + { + "kind": "ScalarField", + "alias": null, + "args": null, + "name": "lastName", + "storageKey": null + } + ], + "type": "Identity" +}; + +module.exports = fragment; diff --git a/components/mutations/LoginMutation.js b/components/mutations/LoginMutation.js new file mode 100644 index 0000000..1f24146 --- /dev/null +++ b/components/mutations/LoginMutation.js @@ -0,0 +1,39 @@ +import { commitMutation, graphql } from 'react-relay'; + +const mutation = graphql` + mutation LoginMutation($email: String!, $password: String!) { + login(email: $email, password: $password) { + identity { + id + lastName + } + isLoggedIn + token + } + } +`; + +function commit(environment, email, password) { + const variables = { + email, + password + }; + + commitMutation(environment, { + mutation, + variables, + onCompleted: response => { + console.log('Success!', response); + if (localStorage) { + localStorage.setItem('token', response.login.token); + } + if (window) { + window.location.reload(); + } + return response; + }, + onError: err => console.error(err) + }); +} + +export default { commit }; diff --git a/components/mutations/__generated__/LoginMutation.graphql.js b/components/mutations/__generated__/LoginMutation.graphql.js new file mode 100644 index 0000000..760baba --- /dev/null +++ b/components/mutations/__generated__/LoginMutation.graphql.js @@ -0,0 +1,223 @@ +/** + * @flow + * @relayHash f229abe459ea0494d23352031f6c9020 + */ + +/* eslint-disable */ + +'use strict'; + +/*:: +import type {ConcreteBatch} from 'relay-runtime'; +export type LoginMutationVariables = {| + email: string; + password: string; +|}; + +export type LoginMutationResponse = {| + +login: ?{| + +identity: ?{| + +id: ?string; + +lastName: ?string; + |}; + +isLoggedIn: ?boolean; + +token: ?string; + |}; +|}; +*/ + + +/* +mutation LoginMutation( + $email: String! + $password: String! +) { + login(email: $email, password: $password) { + identity { + id + lastName + } + isLoggedIn + token + } +} +*/ + +const batch /*: ConcreteBatch*/ = { + "fragment": { + "argumentDefinitions": [ + { + "kind": "LocalArgument", + "name": "email", + "type": "String!", + "defaultValue": null + }, + { + "kind": "LocalArgument", + "name": "password", + "type": "String!", + "defaultValue": null + } + ], + "kind": "Fragment", + "metadata": null, + "name": "LoginMutation", + "selections": [ + { + "kind": "LinkedField", + "alias": null, + "args": [ + { + "kind": "Variable", + "name": "email", + "variableName": "email", + "type": "String!" + }, + { + "kind": "Variable", + "name": "password", + "variableName": "password", + "type": "String!" + } + ], + "concreteType": "User", + "name": "login", + "plural": false, + "selections": [ + { + "kind": "LinkedField", + "alias": null, + "args": null, + "concreteType": "Identity", + "name": "identity", + "plural": false, + "selections": [ + { + "kind": "ScalarField", + "alias": null, + "args": null, + "name": "id", + "storageKey": null + }, + { + "kind": "ScalarField", + "alias": null, + "args": null, + "name": "lastName", + "storageKey": null + } + ], + "storageKey": null + }, + { + "kind": "ScalarField", + "alias": null, + "args": null, + "name": "isLoggedIn", + "storageKey": null + }, + { + "kind": "ScalarField", + "alias": null, + "args": null, + "name": "token", + "storageKey": null + } + ], + "storageKey": null + } + ], + "type": "RootMutation" + }, + "id": null, + "kind": "Batch", + "metadata": {}, + "name": "LoginMutation", + "query": { + "argumentDefinitions": [ + { + "kind": "LocalArgument", + "name": "email", + "type": "String!", + "defaultValue": null + }, + { + "kind": "LocalArgument", + "name": "password", + "type": "String!", + "defaultValue": null + } + ], + "kind": "Root", + "name": "LoginMutation", + "operation": "mutation", + "selections": [ + { + "kind": "LinkedField", + "alias": null, + "args": [ + { + "kind": "Variable", + "name": "email", + "variableName": "email", + "type": "String!" + }, + { + "kind": "Variable", + "name": "password", + "variableName": "password", + "type": "String!" + } + ], + "concreteType": "User", + "name": "login", + "plural": false, + "selections": [ + { + "kind": "LinkedField", + "alias": null, + "args": null, + "concreteType": "Identity", + "name": "identity", + "plural": false, + "selections": [ + { + "kind": "ScalarField", + "alias": null, + "args": null, + "name": "id", + "storageKey": null + }, + { + "kind": "ScalarField", + "alias": null, + "args": null, + "name": "lastName", + "storageKey": null + } + ], + "storageKey": null + }, + { + "kind": "ScalarField", + "alias": null, + "args": null, + "name": "isLoggedIn", + "storageKey": null + }, + { + "kind": "ScalarField", + "alias": null, + "args": null, + "name": "token", + "storageKey": null + } + ], + "storageKey": null + } + ] + }, + "text": "mutation LoginMutation(\n $email: String!\n $password: String!\n) {\n login(email: $email, password: $password) {\n identity {\n id\n lastName\n }\n isLoggedIn\n token\n }\n}\n" +}; + +module.exports = batch; diff --git a/package.json b/package.json index 8e3e46a..ec84801 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "dev": "next", "build": "next build", "start": "next start", - "relay": "relay-compiler --src ./components --schema ./schema.json" + "relay": "relay-compiler --src ./components --schema ./schema.json", + "relay:watch": "relay-compiler --src ./components --schema ./schema.json --watch" } }