-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #13 from ohpyupi/develop
Release v1.2.0
- Loading branch information
Showing
50 changed files
with
1,193 additions
and
250 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,43 @@ | ||
import _ from 'lodash'; | ||
import { ApolloClient } from 'apollo-client'; | ||
import { InMemoryCache } from 'apollo-cache-inmemory'; | ||
import { HttpLink } from 'apollo-link-http'; | ||
import { updateNotification } from './queries/notification'; | ||
import { setContext } from 'apollo-link-context'; | ||
import { updateNotification } from './graphql/notification'; | ||
import { typeDefs } from './graphql/typeDefs'; | ||
import { updateIdToken } from './graphql/auth'; | ||
import { getLocalStorage } from './lib/localStorage'; | ||
|
||
export const apolloClient = new ApolloClient({ | ||
cache: new InMemoryCache(), | ||
resolvers: { | ||
Mutation: { | ||
updateNotification, | ||
}, | ||
}, | ||
link: new HttpLink({ uri: '/graphql' }), | ||
}); | ||
const localStorage = getLocalStorage(); | ||
|
||
apolloClient.writeData({ | ||
data: { | ||
notification: { | ||
__typename: 'Notification', | ||
type: '', | ||
message: '', | ||
export const getApolloClient = async () => { | ||
const httpLink = new HttpLink({ uri: '/graphql' }); | ||
const authLink = setContext((req, { headers }) => ({ | ||
headers: { | ||
...headers, | ||
authorization: `Bearer ${_.get(getLocalStorage(), 'idToken')}`, | ||
}, | ||
})); | ||
const apolloClient = new ApolloClient({ | ||
cache: new InMemoryCache(), | ||
typeDefs, | ||
resolvers: { | ||
Mutation: { | ||
updateNotification, | ||
updateIdToken, | ||
}, | ||
}, | ||
link: authLink.concat(httpLink), | ||
}); | ||
apolloClient.writeData({ | ||
data: { | ||
notification: { | ||
__typename: 'Notification', | ||
type: '', | ||
message: '', | ||
}, | ||
idToken: _.get(localStorage, 'idToken', ''), | ||
}, | ||
}, | ||
}); | ||
}); | ||
return apolloClient; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import _ from 'lodash'; | ||
import React, { useState, useEffect } from 'react'; | ||
import { Redirect } from 'react-router-dom'; | ||
import { useMutation, useQuery } from '@apollo/react-hooks'; | ||
import { Input } from '../../components/input'; | ||
import { Button } from '../../components/button'; | ||
import { Notification } from '../../components/notification'; | ||
import { parseJwtSafe } from '../../lib/utils'; | ||
import { | ||
GET_ID_TOKEN, | ||
RESEND_CHALLENGE, | ||
SOLVE_CHALLENGE, | ||
UPDATED_ID_TOKEN, | ||
} from '../../graphql/auth'; | ||
import { AUTH_STATUS } from '../../lib/constants'; | ||
import { GET_NOTIFICATION, UPDATE_NOTIFICATION } from '../../graphql/notification'; | ||
|
||
export const Challenge = () => { | ||
const [redirectTo, setRedirectTo] = useState(''); | ||
const [challengeCode, setChallengeCode] = useState(''); | ||
const { data: { idToken } } = useQuery(GET_ID_TOKEN); | ||
const { data: { notification } } = useQuery(GET_NOTIFICATION); | ||
const [updateNotification] = useMutation(UPDATE_NOTIFICATION); | ||
const [updateIdToken] = useMutation(UPDATED_ID_TOKEN); | ||
const [resendChallenge] = useMutation(RESEND_CHALLENGE, { | ||
onCompleted(result) { | ||
const message = _.get(result, 'resendChallenge.message'); | ||
return updateNotification({ | ||
type: 'success', | ||
message, | ||
}); | ||
}, | ||
onError(err) { | ||
const message = _.get(err, 'message', 'Something went wrong'); | ||
return updateNotification({ | ||
type: 'warning', | ||
message, | ||
}); | ||
}, | ||
}); | ||
const [solveChallenge] = useMutation(SOLVE_CHALLENGE, { | ||
onCompleted(result) { | ||
const newIdToken = _.get(result, 'solveChallenge.idToken'); | ||
return updateIdToken({ | ||
variables: { | ||
idToken: newIdToken, | ||
}, | ||
}).then(() => setRedirectTo('/user/profile')); | ||
}, | ||
onError(err) { | ||
const message = _.get(err, 'message', 'Something went wrong'); | ||
return updateNotification({ | ||
type: 'warning', | ||
message, | ||
}); | ||
}, | ||
}); | ||
const idTokenPayload = parseJwtSafe(idToken); | ||
const email = _.get(idTokenPayload, 'email'); | ||
const status = _.get(idTokenPayload, 'status'); | ||
const handleCloseErrorMessage = (e) => { | ||
e.preventDefault(); | ||
updateNotification({}); | ||
}; | ||
const handleChallengeCodeChange = (e) => { | ||
e.preventDefault(); | ||
setChallengeCode(_.get(e, 'target.value', '')); | ||
}; | ||
const handleClickResend = (e) => { | ||
e.preventDefault(); | ||
resendChallenge(); | ||
}; | ||
const handleClickSubmit = (e) => { | ||
e.preventDefault(); | ||
solveChallenge({ | ||
variables: { | ||
code: challengeCode, | ||
}, | ||
}); | ||
}; | ||
useEffect(() => { | ||
if (!email) { | ||
setRedirectTo('/login'); | ||
} | ||
if (status === AUTH_STATUS.LOGGED_IN) { | ||
setRedirectTo('/user/profile'); | ||
} | ||
}, []); | ||
if (redirectTo) { | ||
return <Redirect to={redirectTo}/>; | ||
} | ||
return ( | ||
<section id="challenge" className="section"> | ||
<div className="container"> | ||
<h1 className="title">Solve Challenge</h1> | ||
<div className="content"> | ||
<form> | ||
{notification.message ? <Notification className="is-warning" onClose={handleCloseErrorMessage} message={notification.message} /> : null} | ||
<Input label="Email" type="text" className="email-field" placeholder="Email" value={email} disabled={true} readOnly={true}/> | ||
<Input label="Challenge Code" type="text" className="challengecode-field" value={challengeCode} placeholder="Challenge Code" onChange={handleChallengeCodeChange}/> | ||
<Button type="button" className="button is-link" placeholder="Submit" onClick={handleClickSubmit}/> | ||
<Button type="button" placeholder="Resend" onClick={handleClickResend}/> | ||
</form> | ||
</div> | ||
</div> | ||
</section> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import _ from 'lodash'; | ||
import React, { useEffect } from 'react'; | ||
import { withRouter } from 'react-router-dom'; | ||
import { useMutation, useQuery } from '@apollo/react-hooks'; | ||
import { GET_NOTIFICATION, UPDATE_NOTIFICATION } from '../../graphql/notification'; | ||
import { CONFIRM_DEVICE } from '../../graphql/auth'; | ||
import { Spinner } from '../../components/spinner'; | ||
import { Notification } from '../../components/notification'; | ||
|
||
export const ConfirmDevice = withRouter(({ | ||
match: { params: { code } }, | ||
}) => { | ||
const { data: { notification } } = useQuery(GET_NOTIFICATION); | ||
const [updateNotification] = useMutation(UPDATE_NOTIFICATION); | ||
const [confirmDeviceMutation, { called, loading }] = useMutation(CONFIRM_DEVICE, { | ||
onCompleted(result) { | ||
updateNotification({ | ||
variables: { | ||
type: 'success', | ||
message: _.get(result, 'confirmDevice.message'), | ||
}, | ||
}); | ||
}, | ||
onError() { | ||
updateNotification({ | ||
variables: { | ||
type: 'warning', | ||
message: 'Invalid token', | ||
}, | ||
}); | ||
}, | ||
}); | ||
useEffect(() => { | ||
confirmDeviceMutation({ | ||
variables: { | ||
code, | ||
}, | ||
}); | ||
}, []); | ||
const handleCloseErrorMessage = (e) => { | ||
e.preventDefault(); | ||
updateNotification({}); | ||
}; | ||
if (!called || loading) { | ||
return <Spinner/>; | ||
} | ||
return ( | ||
<section id="confirm-device" className="section"> | ||
<div className="container"> | ||
<h1 className="title">Confirm your device</h1> | ||
<div className="content"> | ||
<form> | ||
{notification.message ? <Notification className={`is-${notification.type || 'warning'}`} onClose={handleCloseErrorMessage} message={notification.message} /> : null} | ||
</form> | ||
</div> | ||
</div> | ||
</section> | ||
); | ||
}); |
Oops, something went wrong.