-
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 #137 from AutomatingSciencePipeline/frontend-compo…
…nentization Sign In feedback + Frontend componentization
- Loading branch information
Showing
12 changed files
with
614 additions
and
405 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
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
Submodule Monorepo.wiki
updated
5 files
+12 −4 | Contributing.md | |
+46 −19 | Dev-Guide.md | |
+6 −0 | Home.md | |
+3 −1 | Repository-Guide.md | |
+4 −4 | _Sidebar.md |
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,68 @@ | ||
import Link from 'next/link'; | ||
import Router from 'next/router'; | ||
import { useAuth } from '../../firebase/fbAuth'; | ||
|
||
export interface AlreadySignedInModalProps { | ||
continueButtonMessage: string, | ||
linkTarget: string | ||
} | ||
|
||
export const AlreadySignedInModal = ({ continueButtonMessage, linkTarget }: AlreadySignedInModalProps) => { | ||
const { authService } = useAuth(); | ||
|
||
return <div className='mt-16 sm:mt-24 lg:mt-0 lg:col-span-6'> | ||
<div className='bg-white sm:max-w-md sm:w-full sm:mx-auto sm:rounded-lg sm:overflow-hidden'> | ||
<div className='px-4 py-8 sm:px-10'> | ||
<div> | ||
<p className='text-sm font-medium text-gray-700'> | ||
{"You're already signed in as"} | ||
</p> | ||
<span className='px-2 bg-white text-gray-500'> | ||
{authService.userEmail} | ||
</span> | ||
</div> | ||
|
||
<div className='mt-3'> | ||
<Link href={linkTarget}> | ||
<a | ||
className='space-x-6 flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500' | ||
> | ||
{continueButtonMessage} | ||
</a> | ||
</Link> | ||
</div> | ||
|
||
<div className='mt-3 relative'> | ||
<div | ||
className='absolute inset-0 flex items-center' | ||
aria-hidden='true' | ||
> | ||
<div className='w-full border-t border-gray-300' /> | ||
</div> | ||
<div className='relative flex justify-center text-sm'> | ||
<span className='px-2 bg-white text-gray-500'> | ||
Or | ||
</span> | ||
</div> | ||
</div> | ||
<div className='mt-3'> | ||
<a | ||
className='space-x-6 flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500' | ||
onClick={() => { | ||
return ( | ||
authService | ||
.signOut() | ||
.then(() => { | ||
Router.reload(); | ||
}) | ||
.catch((err) => console.log('Sign out error', err)) | ||
); | ||
}} | ||
> | ||
Log Out | ||
</a> | ||
</div> | ||
</div> | ||
</div> | ||
</div>; | ||
}; |
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,217 @@ | ||
import { joiResolver, useForm } from '@mantine/form'; | ||
import Link from 'next/link'; | ||
import { useState } from 'react'; | ||
import { useAuth } from '../../firebase/fbAuth'; | ||
import { emailSchema, signInSchema } from '../../utils/validators'; | ||
|
||
export const DEFAULT_SIGN_IN_TEXT = 'Sign in'; | ||
export const SIGN_IN_LOADING_TEXT = 'Loading...'; | ||
|
||
export interface SignInModalProps { | ||
afterSignIn: () => void | ||
} | ||
|
||
export const SignInModal = ({ afterSignIn }: SignInModalProps) => { | ||
const form = useForm({ | ||
initialValues: { | ||
email: '', | ||
password: '', | ||
}, | ||
schema: joiResolver(signInSchema), | ||
}); | ||
|
||
const { authService } = useAuth(); | ||
const [buttonDisabled, setButtonDisabled] = useState(false); | ||
const [buttonText, setButtonText] = useState(DEFAULT_SIGN_IN_TEXT); | ||
|
||
return <div className='mt-8 sm:mx-auto sm:w-full sm:max-w-md'> | ||
<div className='bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10'> | ||
<form | ||
className='space-y-6' | ||
onSubmit={form.onSubmit(async (values) => { | ||
const { email, password } = values; | ||
setButtonDisabled(true); | ||
setButtonText(SIGN_IN_LOADING_TEXT); | ||
await authService.signInWithEmailAndPassword( | ||
email, | ||
password | ||
).then(() => { | ||
afterSignIn(); | ||
}).catch((error) => { | ||
alert(`Problem logging in: ${error}`); | ||
setButtonText(DEFAULT_SIGN_IN_TEXT); | ||
setButtonDisabled(false); | ||
}); | ||
})} | ||
> | ||
<div> | ||
<label | ||
htmlFor='email' | ||
className='block text-sm font-medium text-gray-700' | ||
> | ||
Email address | ||
</label> | ||
<div className='mt-1'> | ||
<input | ||
{...form.getInputProps('email')} | ||
type='email' | ||
autoComplete='email' | ||
required | ||
className='appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm' /> | ||
</div> | ||
</div> | ||
|
||
<div> | ||
<label | ||
htmlFor='password' | ||
className='block text-sm font-medium text-gray-700' | ||
> | ||
Password | ||
</label> | ||
<div className='mt-1'> | ||
<input | ||
{...form.getInputProps('password')} | ||
type='password' | ||
autoComplete='current-password' | ||
required | ||
className='appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm' /> | ||
</div> | ||
</div> | ||
|
||
<div> | ||
<button | ||
type='submit' | ||
disabled={buttonDisabled} | ||
className='w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500' | ||
> | ||
{buttonText} | ||
</button> | ||
</div> | ||
|
||
<div className='flex items-center justify-between'> | ||
<div className='text-sm'> | ||
<a | ||
href='#' | ||
className='font-medium text-blue-600 hover:text-blue-500' | ||
onClick={async () => { | ||
const entryEmail = form.getInputProps('email').value; | ||
const { error: validationError, value: validatedEmail } = emailSchema.validate(entryEmail); | ||
if (validationError) { | ||
alert('Please enter a valid email address'); | ||
} else { | ||
try { | ||
await authService.sendPasswordResetEmail(validatedEmail); | ||
alert('Password reset email sent'); | ||
} catch (error) { | ||
alert(`Problem sending password reset email: ${error}`); | ||
} | ||
} | ||
}} | ||
> | ||
Forgot your password? | ||
</a> | ||
</div> | ||
</div> | ||
</form> | ||
|
||
<div className='mt-6'> | ||
<div className='relative'> | ||
<div className='absolute inset-0 flex items-center'> | ||
<div className='w-full border-t border-gray-300' /> | ||
</div> | ||
<div className='relative flex justify-center text-sm'> | ||
<span className='px-2 bg-white text-gray-500'> | ||
Or continue with | ||
</span> | ||
</div> | ||
</div> | ||
|
||
<span className='px-2 bg-white text-gray-500'> | ||
(OAuth login support coming soon™) | ||
</span> | ||
|
||
{/* TODO implement OAuth sign in */} | ||
{/* <div className='mt-6 grid grid-cols-3 gap-3'> | ||
<div> | ||
<a | ||
href='#' | ||
className='w-full inline-flex justify-center py-2 px-4 border border-gray-300 rounded-md shadow-sm bg-white text-sm font-medium text-gray-500 hover:bg-gray-50' | ||
> | ||
<span className='sr-only'>Sign in with Facebook</span> | ||
<svg | ||
className='w-5 h-5' | ||
aria-hidden='true' | ||
fill='currentColor' | ||
viewBox='0 0 20 20' | ||
> | ||
<path | ||
fillRule='evenodd' | ||
d='M20 10c0-5.523-4.477-10-10-10S0 4.477 0 10c0 4.991 3.657 9.128 8.438 9.878v-6.987h-2.54V10h2.54V7.797c0-2.506 1.492-3.89 3.777-3.89 1.094 0 2.238.195 2.238.195v2.46h-1.26c-1.243 0-1.63.771-1.63 1.562V10h2.773l-.443 2.89h-2.33v6.988C16.343 19.128 20 14.991 20 10z' | ||
clipRule='evenodd' /> | ||
</svg> | ||
</a> | ||
</div> | ||
<div> | ||
<a | ||
href='#' | ||
className='w-full inline-flex justify-center py-2 px-4 border border-gray-300 rounded-md shadow-sm bg-white text-sm font-medium text-gray-500 hover:bg-gray-50' | ||
> | ||
<span className='sr-only'>Sign in with Twitter</span> | ||
<svg | ||
className='w-5 h-5' | ||
aria-hidden='true' | ||
fill='currentColor' | ||
viewBox='0 0 20 20' | ||
> | ||
<path d='M6.29 18.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0020 3.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-6.993 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.073 4.073 0 01.8 7.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 010 16.407a11.616 11.616 0 006.29 1.84' /> | ||
</svg> | ||
</a> | ||
</div> | ||
<div> | ||
<a | ||
href='#' | ||
className='w-full inline-flex justify-center py-2 px-4 border border-gray-300 rounded-md shadow-sm bg-white text-sm font-medium text-gray-500 hover:bg-gray-50' | ||
> | ||
<span className='sr-only'>Sign in with GitHub</span> | ||
<svg | ||
className='w-5 h-5' | ||
aria-hidden='true' | ||
fill='currentColor' | ||
viewBox='0 0 20 20' | ||
> | ||
<path | ||
fillRule='evenodd' | ||
d='M10 0C4.477 0 0 4.484 0 10.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0110 4.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.203 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.942.359.31.678.921.678 1.856 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0020 10.017C20 4.484 15.522 0 10 0z' | ||
clipRule='evenodd' /> | ||
</svg> | ||
</a> | ||
</div> | ||
</div> */} | ||
</div> | ||
<div className='mt-3 relative'> | ||
<div | ||
className='absolute inset-0 flex items-center' | ||
aria-hidden='true' | ||
> | ||
<div className='w-full border-t border-gray-300' /> | ||
</div> | ||
<div className='relative flex justify-center text-sm'> | ||
<span className='px-2 bg-white text-gray-500'> | ||
No account yet? | ||
</span> | ||
</div> | ||
</div> | ||
<div className='mt-3'> | ||
<Link href={'/'}> | ||
<a | ||
className='space-x-6 flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500' | ||
> | ||
Go to the Sign Up Page | ||
</a> | ||
</Link> | ||
</div> | ||
</div> | ||
</div>; | ||
}; |
Oops, something went wrong.