Revert "issue-129 Add custom auth ui/ux"
This reverts commit fc4906757a.
This commit is contained in:
@@ -18,7 +18,7 @@ export const handler = async (req, _context) => {
|
||||
email: 'k.hutten@protonmail.ch',
|
||||
confirmation_sent_at: '2020-10-19T18:09:01Z',
|
||||
app_metadata: { provider: 'email' },
|
||||
user_metadata: { full_name: 'sick_dog', userName: 'hi bob' },
|
||||
user_metadata: { full_name: 'sick_dog' },
|
||||
created_at: '2020-10-19T18:09:01Z',
|
||||
updated_at: '2020-10-19T18:09:01Z'
|
||||
}
|
||||
@@ -62,12 +62,12 @@ export const handler = async (req, _context) => {
|
||||
db.user.findOne({
|
||||
where: { userName: seed },
|
||||
})
|
||||
const userNameSeed = enforceAlphaNumeric(user?.user_metadata?.userName)
|
||||
const userNameSeed = enforceAlphaNumeric(email.split('@')[0])
|
||||
const userName = await generateUniqueString(userNameSeed, isUniqueCallback) // TODO maybe come up with a better default userName?
|
||||
const input = {
|
||||
email,
|
||||
userName,
|
||||
name: user?.user_metadata?.full_name,
|
||||
name: user.user_metadata && user.user_metadata.full_name,
|
||||
id: user.id,
|
||||
}
|
||||
await createUserInsecure({ input })
|
||||
|
||||
@@ -70,7 +70,7 @@ import { AuthenticationError, ForbiddenError, parseJWT } from '@redwoodjs/api'
|
||||
* return await db.user.findOne({ where: { decoded.email } })
|
||||
* }
|
||||
*
|
||||
* @example - User info is contained in the decoded token and roles extracted
|
||||
* @example - User info is conatined in the decoded token and roles extracted
|
||||
*
|
||||
* export const getCurrentUser = async (decoded, { _token, _type }) => {
|
||||
* return { ...decoded, roles: parseJWT({ decoded }).roles }
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
port = 8910
|
||||
apiProxyPath = "/.netlify/functions"
|
||||
includeEnvironmentVariables = ['GOOGLE_ANALYTICS_ID']
|
||||
experimentalFastRefresh = true
|
||||
[api]
|
||||
port = 8911
|
||||
[browser]
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"event": "signup",
|
||||
"instance_id": "403b7d63-17f9-48f1-a85f-3d6b41c7dad1",
|
||||
"user": {
|
||||
"id": "641222ee-3e61-4253-8c11-9f764779bcc5",
|
||||
"aud": "",
|
||||
"role": "",
|
||||
"email": "k.hutten2@protonmail.ch",
|
||||
"confirmation_sent_at": "2020-10-19T18:09:01Z",
|
||||
"app_metadata": { "provider": "email" },
|
||||
"user_metadata": { "full_name": "sick_dog", "userName": "hi bob" },
|
||||
"created_at": "2020-10-19T18:09:01Z",
|
||||
"updated_at": "2020-10-19T18:09:01Z"
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^4.11.0",
|
||||
"@redwoodjs/auth": "^0.21.0",
|
||||
"@redwoodjs/auth": "^0.20.0",
|
||||
"@redwoodjs/forms": "^0.20.0",
|
||||
"@redwoodjs/router": "^0.20.0",
|
||||
"@redwoodjs/web": "^0.20.0",
|
||||
@@ -22,7 +22,6 @@
|
||||
"controlkit": "^0.1.9",
|
||||
"get-active-classes": "^0.0.11",
|
||||
"golden-layout": "^1.5.9",
|
||||
"gotrue-js": "^0.9.27",
|
||||
"jquery": "^3.5.1",
|
||||
"monaco-editor": "^0.20.0",
|
||||
"monaco-editor-webpack-plugin": "^1.9.1",
|
||||
|
||||
@@ -32,9 +32,6 @@ const Routes = () => {
|
||||
)
|
||||
return (
|
||||
<Router>
|
||||
<Route path="/account-recovery/update-password" page={UpdatePasswordPage} name="updatePassword" />
|
||||
{/* <Route path="/account-recovery/update-password/{recoveryToken}" page={UpdatePasswordPage} name="updatePassword" /> */}
|
||||
<Route path="/account-recovery" page={AccountRecoveryPage} name="accountRecovery" />
|
||||
<Route path="/" page={PartsPage} name="home" />
|
||||
<Route notfound page={NotFoundPage} />
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ const InputText = ({ value, isEditable, onChange, className }) => {
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div className="absolute inset-0 mb-2 rounded bg-gray-200 shadow-inners" />
|
||||
<div className="absolute inset-0 mb-2 rounded bg-gray-200 shadow-inner bg-gray-100" />
|
||||
<input
|
||||
className="pl-2 pt-1 text-indigo-800 font-medium mb-px pb-px bg-transparent relative"
|
||||
onChange={onChange}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
import { getActiveClasses } from 'get-active-classes'
|
||||
import { TextField, FieldError } from '@redwoodjs/forms'
|
||||
import { useFormContext } from 'react-hook-form'
|
||||
|
||||
// COPY of InputText but using TextField for use with redwood forms. Maybe I should combine them back into one or otherwise try and share code between these two.
|
||||
|
||||
const InputText = ({ type = 'text', className, name, validation }) => {
|
||||
const { errors } = useFormContext()
|
||||
return (
|
||||
<>
|
||||
<div className={getActiveClasses('relative inline-block', className)}>
|
||||
<FieldError
|
||||
className="absolute -my-4 text-sm text-red-500 font-ropa-sans"
|
||||
name={name}
|
||||
/>
|
||||
<div
|
||||
className={getActiveClasses(
|
||||
'absolute inset-0 mb-2 rounded bg-gray-200 shadow-inner',
|
||||
{ 'border border-red-500': errors[name] }
|
||||
)}
|
||||
/>
|
||||
<TextField
|
||||
className={getActiveClasses(
|
||||
'pl-2 pt-1 text-indigo-800 font-medium mb-px pb-px bg-transparent relative w-full'
|
||||
)}
|
||||
name={name}
|
||||
readOnly={false}
|
||||
type={type}
|
||||
validation={validation}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default InputText
|
||||
@@ -1,7 +0,0 @@
|
||||
import InputTextForm from './InputTextForm'
|
||||
|
||||
export const generated = () => {
|
||||
return <InputTextForm />
|
||||
}
|
||||
|
||||
export default { title: 'Components/InputTextForm' }
|
||||
@@ -1,11 +0,0 @@
|
||||
import { render } from '@redwoodjs/testing'
|
||||
|
||||
import InputTextForm from './InputTextForm'
|
||||
|
||||
describe('InputTextForm', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<InputTextForm />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
@@ -7,18 +7,17 @@ import {
|
||||
} from './mockEditorParts'
|
||||
import Svg from 'src/components/Svg'
|
||||
import OutBound from 'src/components/OutBound'
|
||||
import { useAuth } from '@redwoodjs/auth'
|
||||
import ReactGA from 'react-ga'
|
||||
import LoginModal from 'src/components/LoginModal'
|
||||
import { useState } from 'react'
|
||||
|
||||
const LandingSection = () => {
|
||||
const [isLoginModalOpen, setIsLoginModalOpen] = useState(false)
|
||||
const recordedLogin = async () => {
|
||||
const { logIn } = useAuth()
|
||||
const recordedLogin = () => {
|
||||
ReactGA.event({
|
||||
category: 'login',
|
||||
action: 'landing section CTA',
|
||||
})
|
||||
setIsLoginModalOpen(true)
|
||||
logIn()
|
||||
}
|
||||
return (
|
||||
<div className="mt-16">
|
||||
@@ -164,12 +163,10 @@ const LandingSection = () => {
|
||||
with more integrations coming soon.
|
||||
</p>
|
||||
<button
|
||||
className="bg-texture bg-purple-800 text-center w-full py-6 rounded-b-md border border-indigo-300 border-opacity-0 hover:border-opacity-100 hover:shadow-xl"
|
||||
className="font-bold text-2xl bg-texture bg-purple-800 text-center w-full py-6 rounded-b-md border border-indigo-300 border-opacity-0 hover:border-opacity-100 hover:shadow-xl"
|
||||
onClick={recordedLogin}
|
||||
>
|
||||
<span className="font-bold text-2xl text-indigo-200">
|
||||
Start Hacking Now
|
||||
</span>
|
||||
<span className="text-indigo-200">Start Hacking Now</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -182,11 +179,6 @@ const LandingSection = () => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<LoginModal
|
||||
open={isLoginModalOpen}
|
||||
onClose={() => setIsLoginModalOpen(false)}
|
||||
shouldStartWithSignup
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
import { useState } from 'react'
|
||||
import Dialog from '@material-ui/core/Dialog'
|
||||
import Tab from '@material-ui/core/Tab'
|
||||
import Tabs from '@material-ui/core/Tabs'
|
||||
import InputTextForm from 'src/components/InputTextForm'
|
||||
import OutBound from 'src/components/OutBound'
|
||||
import { Form, Submit } from '@redwoodjs/forms'
|
||||
import { useAuth } from '@redwoodjs/auth'
|
||||
import { Link, routes } from '@redwoodjs/router'
|
||||
|
||||
const LoginModal = ({ open, onClose, shouldStartWithSignup = false }) => {
|
||||
const { logIn, signUp } = useAuth()
|
||||
|
||||
const [tab, setTab] = useState(shouldStartWithSignup ? 0 : 1)
|
||||
const onTabChange = (_, newValue) => {
|
||||
setTab(newValue)
|
||||
setError('')
|
||||
}
|
||||
const [checkBox, setCheckBox] = useState(true)
|
||||
const [error, setError] = useState('')
|
||||
|
||||
const onSubmitSignUp = async ({ email, password, name, userName }) => {
|
||||
try {
|
||||
setError('')
|
||||
await signUp({
|
||||
email,
|
||||
password,
|
||||
remember: { full_name: name, userName },
|
||||
})
|
||||
onClose()
|
||||
} catch (errorEvent) {
|
||||
setError(errorEvent?.json?.error_description)
|
||||
}
|
||||
}
|
||||
const onSubmitSignIn = async ({ email, password }) => {
|
||||
try {
|
||||
setError('')
|
||||
await logIn({ email, password, remember: true })
|
||||
onClose()
|
||||
} catch (errorEvent) {
|
||||
setError(errorEvent?.json?.error_description)
|
||||
}
|
||||
}
|
||||
return (
|
||||
<Dialog open={open} onClose={onClose}>
|
||||
<div className="bg-gray-100 max-w-2xl rounded-lg shadow-lg">
|
||||
<Tabs
|
||||
value={tab}
|
||||
onChange={onTabChange}
|
||||
centered
|
||||
textColor="primary"
|
||||
indicatorColor="primary"
|
||||
>
|
||||
<Tab label="Sign Up" />
|
||||
<Tab label="Sign In" />
|
||||
</Tabs>
|
||||
{error && (
|
||||
<div className="text-sm text-red-500 font-ropa-sans pt-4 text-center">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
{tab === 0 ? (
|
||||
<SignUpForm
|
||||
onSubmitSignUp={onSubmitSignUp}
|
||||
checkBox={checkBox}
|
||||
setCheckBox={setCheckBox}
|
||||
/>
|
||||
) : (
|
||||
<SignInForm onSubmitSignIn={onSubmitSignIn} />
|
||||
)}
|
||||
</div>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
const Field = ({ name, type = 'text', validation }) => (
|
||||
<>
|
||||
<span className="capitalize text-gray-500 text-sm align-middle my-3">
|
||||
{name}:
|
||||
</span>
|
||||
<InputTextForm
|
||||
type={type}
|
||||
className="text-xl"
|
||||
name={name}
|
||||
validation={validation}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
|
||||
const HeroButton = ({ text }) => (
|
||||
<Submit className="bg-texture bg-purple-800 py-6 w-full flex items-center justify-center rounded-b border border-indigo-300 border-opacity-0 hover:border-opacity-100 hover:shadow-xl">
|
||||
<span className="font-bold text-2xl text-indigo-200">{text}</span>
|
||||
</Submit>
|
||||
)
|
||||
|
||||
const SignInForm = ({ onSubmitSignIn }) => (
|
||||
<Form className="w-full" onSubmit={onSubmitSignIn}>
|
||||
<div className="p-8">
|
||||
<div
|
||||
className="grid items-center gap-2"
|
||||
style={{ gridTemplateColumns: 'auto 1fr' }}
|
||||
>
|
||||
<Field
|
||||
name="email"
|
||||
validation={{
|
||||
required: true,
|
||||
pattern: {
|
||||
value: /[^@]+@[^.]+\..+/,
|
||||
message: 'please enter a valid email address',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<Field
|
||||
name="password"
|
||||
type="password"
|
||||
validation={{ required: true }}
|
||||
/>
|
||||
</div>
|
||||
<Link
|
||||
to={routes.accountRecovery()}
|
||||
className="underline text-sm text-gray-500 block text-center"
|
||||
>
|
||||
forgot your password?
|
||||
</Link>
|
||||
</div>
|
||||
<HeroButton text="Sign In" />
|
||||
</Form>
|
||||
)
|
||||
|
||||
const SignUpForm = ({ onSubmitSignUp, checkBox, setCheckBox }) => (
|
||||
<Form className="w-full" onSubmit={onSubmitSignUp}>
|
||||
<div className="p-8">
|
||||
<div
|
||||
className="grid items-center gap-2"
|
||||
style={{ gridTemplateColumns: 'auto 1fr' }}
|
||||
>
|
||||
<Field name="name" validation={{ required: true }} />
|
||||
<Field
|
||||
name="userName"
|
||||
validation={{
|
||||
required: true,
|
||||
pattern: {
|
||||
value: /^[a-zA-Z0-9-_]+$/,
|
||||
message: 'Only alphanumeric and dash characters allowed',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<Field
|
||||
name="email"
|
||||
validation={{
|
||||
required: true,
|
||||
pattern: {
|
||||
value: /[^@]+@[^.]+\..+/,
|
||||
message: 'please enter a valid email address',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<Field
|
||||
name="password"
|
||||
type="password"
|
||||
validation={{ required: true }}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex pt-4">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={checkBox}
|
||||
onChange={() => setCheckBox(!checkBox)}
|
||||
/>{' '}
|
||||
<span className="pl-4 text-gray-500 text-sm max-w-sm">
|
||||
Stay up-to-date with CadHub's progress with the founder's (
|
||||
<OutBound className="underline" to="https://twitter.com/IrevDev">
|
||||
Kurt's
|
||||
</OutBound>
|
||||
) newsletter
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<HeroButton text="Sign Up" />
|
||||
</Form>
|
||||
)
|
||||
|
||||
export default LoginModal
|
||||
@@ -1,7 +0,0 @@
|
||||
import LoginModal from './LoginModal'
|
||||
|
||||
export const generated = () => {
|
||||
return <LoginModal open={true} />
|
||||
}
|
||||
|
||||
export default { title: 'Components/LoginModal' }
|
||||
@@ -1,11 +0,0 @@
|
||||
import { render } from '@redwoodjs/testing'
|
||||
|
||||
import LoginModal from './LoginModal'
|
||||
|
||||
describe('LoginModal', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<LoginModal />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
@@ -1,6 +1,5 @@
|
||||
import { AuthProvider } from '@redwoodjs/auth'
|
||||
import GoTrue from 'gotrue-js'
|
||||
|
||||
import netlifyIdentity from 'netlify-identity-widget'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { RedwoodProvider, FatalErrorBoundary } from '@redwoodjs/web'
|
||||
import FatalErrorPage from 'src/pages/FatalErrorPage'
|
||||
@@ -17,6 +16,8 @@ import './cascade/css/main.css'
|
||||
import 'monaco-editor/min/vs/editor/editor.main.css'
|
||||
import './index.css'
|
||||
|
||||
netlifyIdentity.init()
|
||||
|
||||
function initCascadeStudio() {
|
||||
// if ('serviceWorker' in navigator) {
|
||||
// navigator.serviceWorker.register('service-worker.js').then(function(registration) {
|
||||
@@ -48,14 +49,9 @@ function initCascadeStudio() {
|
||||
}
|
||||
initCascadeStudio()
|
||||
|
||||
const goTrueClient = new GoTrue({
|
||||
APIUrl: 'https://cadhub.xyz/.netlify/identity',
|
||||
setCookie: true,
|
||||
})
|
||||
|
||||
ReactDOM.render(
|
||||
<FatalErrorBoundary page={FatalErrorPage}>
|
||||
<AuthProvider client={goTrueClient} type="goTrue">
|
||||
<AuthProvider client={netlifyIdentity} type="netlify">
|
||||
<RedwoodProvider>
|
||||
<Routes />
|
||||
</RedwoodProvider>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { Link, routes, navigate } from '@redwoodjs/router'
|
||||
import { Link, routes } from '@redwoodjs/router'
|
||||
import { useAuth } from '@redwoodjs/auth'
|
||||
import { Flash, useQuery, useFlash } from '@redwoodjs/web'
|
||||
import { Flash } from '@redwoodjs/web'
|
||||
import Tooltip from '@material-ui/core/Tooltip'
|
||||
import { useQuery } from '@redwoodjs/web'
|
||||
import Popover from '@material-ui/core/Popover'
|
||||
import { getActiveClasses } from 'get-active-classes'
|
||||
import { useLocation } from '@redwoodjs/router'
|
||||
import LoginModal from 'src/components/LoginModal'
|
||||
import ReactGA from 'react-ga'
|
||||
|
||||
export const QUERY = gql`
|
||||
@@ -26,13 +26,11 @@ let previousSubmission = ''
|
||||
let previousUserID = ''
|
||||
|
||||
const MainLayout = ({ children }) => {
|
||||
const { logOut, isAuthenticated, currentUser, client } = useAuth()
|
||||
const { addMessage } = useFlash()
|
||||
const { logIn, logOut, isAuthenticated, currentUser } = useAuth()
|
||||
const { data, loading } = useQuery(QUERY, {
|
||||
skip: !currentUser?.sub,
|
||||
variables: { id: currentUser?.sub },
|
||||
})
|
||||
const [isLoginModalOpen, setIsLoginModalOpen] = useState(false)
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const [anchorEl, setAnchorEl] = useState(null)
|
||||
const [popoverId, setPopoverId] = useState(undefined)
|
||||
@@ -61,7 +59,7 @@ const MainLayout = ({ children }) => {
|
||||
category: 'login',
|
||||
action: 'navbar login',
|
||||
})
|
||||
setIsLoginModalOpen(true)
|
||||
logIn()
|
||||
}
|
||||
|
||||
const { pathname, params } = useLocation()
|
||||
@@ -87,38 +85,6 @@ const MainLayout = ({ children }) => {
|
||||
previousUserID = currentUser
|
||||
}
|
||||
}, [data, currentUser, isAuthenticated])
|
||||
const hash = window.location.hash
|
||||
useEffect(() => {
|
||||
const [key, token] = hash.slice(1).split('=')
|
||||
if (key === 'confirmation_token') {
|
||||
console.log('confirming with', token)
|
||||
client
|
||||
.confirm(token, true)
|
||||
.then(() => {
|
||||
addMessage('Email confirmed', { classes: 'rw-flash-success' })
|
||||
})
|
||||
.catch(() => {
|
||||
addMessage('Problem confirming email', {
|
||||
classes: 'bg-red-300 text-red-900',
|
||||
})
|
||||
})
|
||||
} else if (key === 'recovery_token') {
|
||||
// http://localhost:8910/#recovery_token=LwsC-KpgmiDwGo-ZcGH0tA
|
||||
// https://mandrillapp.com/track/click/31128206/cadhub.xyz?p=eyJzIjoiWFlFbDk5YTVYU0FOSmEtZ3ZtUXlDSW13QURrIiwidiI6MSwicCI6IntcInVcIjozMTEyODIwNixcInZcIjoxLFwidXJsXCI6XCJodHRwczpcXFwvXFxcL2NhZGh1Yi54eXpcXFwvI3JlY292ZXJ5X3Rva2VuPUx3c0MtS3BnbWlEd0dvLVpjR0gwdEFcIixcImlkXCI6XCJjODU1ZWM1MjZiZmQ0Y2JmYmUyNmM4OTk2ZGU4ODczOFwiLFwidXJsX2lkc1wiOltcIjJkMjljMDI0NTY5MzcxODcxMmI0ODA0M2U3MDYyOTA1ZDc1NzVkNjlcIl19In0
|
||||
// #recovery_token=LwsC-KpgmiDwGo-ZcGH0tA
|
||||
// navigate(routes.updatePassword({ recoveryToken: token }))
|
||||
client
|
||||
.recover(token, true)
|
||||
.then(() => {
|
||||
navigate(routes.updatePassword())
|
||||
})
|
||||
.catch(() => {
|
||||
addMessage('Problem recovering account', {
|
||||
classes: 'bg-red-300 text-red-900',
|
||||
})
|
||||
})
|
||||
}
|
||||
}, [hash, client]) // complaining about not having addMessage, however adding it puts useEffect into a loop
|
||||
return (
|
||||
<>
|
||||
<header id="cadhub-main-header">
|
||||
@@ -232,11 +198,7 @@ const MainLayout = ({ children }) => {
|
||||
)}
|
||||
</nav>
|
||||
</header>
|
||||
<Flash timeout={1500} />
|
||||
<LoginModal
|
||||
open={isLoginModalOpen}
|
||||
onClose={() => setIsLoginModalOpen(false)}
|
||||
/>
|
||||
<Flash timeout={1000} />
|
||||
<main>{children}</main>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
import { routes, navigate } from '@redwoodjs/router'
|
||||
import { useAuth } from '@redwoodjs/auth'
|
||||
import { Form, Submit } from '@redwoodjs/forms'
|
||||
import { useFlash } from '@redwoodjs/web'
|
||||
|
||||
import InputTextForm from 'src/components/InputTextForm'
|
||||
import MainLayout from 'src/layouts/MainLayout'
|
||||
import Seo from 'src/components/Seo/Seo'
|
||||
|
||||
const AccountRecoveryPage = () => {
|
||||
const { addMessage } = useFlash()
|
||||
const { client } = useAuth()
|
||||
const onSubmit = ({ email }) => {
|
||||
client
|
||||
.requestPasswordRecovery(email)
|
||||
.then(() => {
|
||||
addMessage('Email sent', { classes: 'rw-flash-success' })
|
||||
setTimeout(() => {
|
||||
navigate(routes.home())
|
||||
}, 500)
|
||||
})
|
||||
.catch(() => {
|
||||
addMessage('Problem sending email', {
|
||||
classes: 'bg-red-300 text-red-900',
|
||||
})
|
||||
})
|
||||
}
|
||||
return (
|
||||
<MainLayout>
|
||||
<Seo
|
||||
title="Account recovery"
|
||||
description="Send recovery email"
|
||||
lang="en-US"
|
||||
/>
|
||||
|
||||
<section className="max-w-md mx-auto mt-20">
|
||||
<h2 className="text-xl text-indigo-500 pb-4">Send recovery email</h2>
|
||||
<Form onSubmit={onSubmit}>
|
||||
<div
|
||||
className="grid items-center gap-2"
|
||||
style={{ gridTemplateColumns: 'auto 1fr' }}
|
||||
>
|
||||
<span className="capitalize text-gray-500 text-sm align-middle my-3">
|
||||
email:
|
||||
</span>
|
||||
<InputTextForm
|
||||
className="text-xl"
|
||||
name="email"
|
||||
validation={{
|
||||
required: true,
|
||||
pattern: {
|
||||
value: /[^@]+@[^.]+\..+/,
|
||||
message: 'please enter a valid email address',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<Submit className="bg-indigo-200 text-indigo-800 p-2 px-4 shadow hover:shadow-lg mt-4 rounded">
|
||||
Send email
|
||||
</Submit>
|
||||
</Form>
|
||||
</section>
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default AccountRecoveryPage
|
||||
@@ -1,7 +0,0 @@
|
||||
import AccountRecoveryPage from './AccountRecoveryPage'
|
||||
|
||||
export const generated = () => {
|
||||
return <AccountRecoveryPage />
|
||||
}
|
||||
|
||||
export default { title: 'Pages/AccountRecoveryPage' }
|
||||
@@ -1,11 +0,0 @@
|
||||
import { render } from '@redwoodjs/testing'
|
||||
|
||||
import AccountRecoveryPage from './AccountRecoveryPage'
|
||||
|
||||
describe('AccountRecoveryPage', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<AccountRecoveryPage />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
@@ -1,82 +0,0 @@
|
||||
import { routes, navigate } from '@redwoodjs/router'
|
||||
import { useAuth } from '@redwoodjs/auth'
|
||||
import { Form, Submit } from '@redwoodjs/forms'
|
||||
import { useFlash } from '@redwoodjs/web'
|
||||
|
||||
import InputTextForm from 'src/components/InputTextForm'
|
||||
import MainLayout from 'src/layouts/MainLayout'
|
||||
import Seo from 'src/components/Seo/Seo'
|
||||
|
||||
const UpdatePasswordPage = () => {
|
||||
const { addMessage } = useFlash()
|
||||
const { client } = useAuth()
|
||||
const onSubmit = ({ password, confirm }) => {
|
||||
if (password !== confirm) {
|
||||
addMessage("Passwords don't match, try again", {
|
||||
classes: 'bg-red-300 text-red-900',
|
||||
})
|
||||
return
|
||||
}
|
||||
client
|
||||
.currentUser()
|
||||
.update({ password })
|
||||
.then(() => {
|
||||
addMessage('Email updated', { classes: 'rw-flash-success' })
|
||||
setTimeout(() => {
|
||||
navigate(routes.home())
|
||||
}, 500)
|
||||
})
|
||||
.catch(() => {
|
||||
addMessage('Problem updating email', {
|
||||
classes: 'bg-red-300 text-red-900',
|
||||
})
|
||||
})
|
||||
}
|
||||
return (
|
||||
<MainLayout>
|
||||
<Seo
|
||||
title="Account recovery"
|
||||
description="Send recovery email"
|
||||
lang="en-US"
|
||||
/>
|
||||
|
||||
<section className="max-w-md mx-auto mt-20">
|
||||
<h2 className="text-xl text-indigo-500 pb-4">Reset Password</h2>
|
||||
<Form onSubmit={onSubmit}>
|
||||
<div
|
||||
className="grid items-center gap-2"
|
||||
style={{ gridTemplateColumns: 'auto 1fr' }}
|
||||
>
|
||||
<span className="capitalize text-gray-500 text-sm align-middle my-3">
|
||||
password:
|
||||
</span>
|
||||
<InputTextForm
|
||||
className="text-xl"
|
||||
name="email"
|
||||
type="password"
|
||||
validation={{
|
||||
required: true,
|
||||
}}
|
||||
/>
|
||||
<span className="capitalize text-gray-500 text-sm align-middle my-3">
|
||||
confirm:
|
||||
</span>
|
||||
<InputTextForm
|
||||
className="text-xl"
|
||||
name="email"
|
||||
type="password"
|
||||
validation={{
|
||||
required: true,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<Submit className="bg-indigo-200 text-indigo-800 p-2 px-4 shadow hover:shadow-lg mt-4 rounded">
|
||||
Update
|
||||
</Submit>
|
||||
</Form>
|
||||
</section>
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default UpdatePasswordPage
|
||||
@@ -1,7 +0,0 @@
|
||||
import UpdatePasswordPage from './UpdatePasswordPage'
|
||||
|
||||
export const generated = () => {
|
||||
return <UpdatePasswordPage />
|
||||
}
|
||||
|
||||
export default { title: 'Pages/UpdatePasswordPage' }
|
||||
@@ -1,11 +0,0 @@
|
||||
import { render } from '@redwoodjs/testing'
|
||||
|
||||
import UpdatePasswordPage from './UpdatePasswordPage'
|
||||
|
||||
describe('UpdatePasswordPage', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<UpdatePasswordPage />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
20
yarn.lock
20
yarn.lock
@@ -2366,10 +2366,10 @@
|
||||
lodash.omitby "^4.6.0"
|
||||
merge-graphql-schemas "^1.7.6"
|
||||
|
||||
"@redwoodjs/auth@^0.21.0":
|
||||
version "0.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@redwoodjs/auth/-/auth-0.21.0.tgz#967deef0d0421ea9f6bc205857ad9265d2f5df55"
|
||||
integrity sha512-o3HuRTs79BqmnZX2zvK6+ffebxJE+T/nqwDDdOmCjXUitSsYbLSJkG4ffUuMtSWCFCxf/ytaFB245nS8Vin3XQ==
|
||||
"@redwoodjs/auth@^0.20.0":
|
||||
version "0.20.0"
|
||||
resolved "https://registry.yarnpkg.com/@redwoodjs/auth/-/auth-0.20.0.tgz#c08c0b735a0b09ef84dc6d357fa2803d61f1d389"
|
||||
integrity sha512-M1rPtiXzU7YagQ120zEkp5qvJruWRcFLUfBhgexGYgnEkqFIKFGLQL9pBywoZ6kxNjI7x/pbghz6FS7H/lzw/g==
|
||||
|
||||
"@redwoodjs/cli@^0.20.0":
|
||||
version "0.20.0"
|
||||
@@ -8671,13 +8671,6 @@ good-listener@^1.2.2:
|
||||
dependencies:
|
||||
delegate "^3.1.2"
|
||||
|
||||
gotrue-js@^0.9.27:
|
||||
version "0.9.27"
|
||||
resolved "https://registry.yarnpkg.com/gotrue-js/-/gotrue-js-0.9.27.tgz#ed01b47e97781f10f26458ff77d83d97bcc65e08"
|
||||
integrity sha512-XSQ9XGELrnf6bKYaGk+2z1E6aW6+wZ3S6ns3JQz9tXesBuwVPDv/xOTTZ/Qrtu85GJgxTjhJH447w09a73Tneg==
|
||||
dependencies:
|
||||
micro-api-client "^3.2.1"
|
||||
|
||||
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.4:
|
||||
version "4.2.4"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
|
||||
@@ -11338,11 +11331,6 @@ methods@~1.1.2:
|
||||
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
|
||||
integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
|
||||
|
||||
micro-api-client@^3.2.1:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/micro-api-client/-/micro-api-client-3.3.0.tgz#52dd567d322f10faffe63d19d4feeac4e4ffd215"
|
||||
integrity sha512-y0y6CUB9RLVsy3kfgayU28746QrNMpSm9O/AYGNsBgOkJr/X/Jk0VLGoO8Ude7Bpa8adywzF+MzXNZRFRsNPhg==
|
||||
|
||||
microevent.ts@~0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/microevent.ts/-/microevent.ts-0.1.1.tgz#70b09b83f43df5172d0205a63025bce0f7357fa0"
|
||||
|
||||
Reference in New Issue
Block a user