More forms and backend NPE fix
This commit is contained in:
parent
53dd50d098
commit
5533e0a995
|
@ -1,7 +1,7 @@
|
|||
import {parse} from 'url'
|
||||
import UserManager from './user'
|
||||
import {Request, Response} from 'express'
|
||||
import SessionManager, { SessionRequest } from './session'
|
||||
import SessionManager, {Session, SessionRequest} from './session'
|
||||
import {UserProperties} from './types'
|
||||
|
||||
let userManager, sessionManager
|
||||
|
@ -83,7 +83,7 @@ const handleSignin = async (req: Request, res: Response) => {
|
|||
const ip = req.ip.split('.').map(num => parseInt(num))
|
||||
|
||||
console.log('Got sign in request with params', JSON.stringify(params))
|
||||
const session = await sessionManager.initiateSession({
|
||||
const session: Session = await sessionManager.initiateSession({
|
||||
hash: params.hash as string,
|
||||
email: params.email as string,
|
||||
ipAddress: ip,
|
||||
|
@ -97,7 +97,6 @@ const handleSignin = async (req: Request, res: Response) => {
|
|||
return
|
||||
}
|
||||
|
||||
|
||||
res.status(200)
|
||||
// todo: invalidate session invite
|
||||
res.setHeader('set-cookie', `__session=${session.hash}; Secure;`)
|
||||
|
@ -126,7 +125,7 @@ const handlePostSession = async (req: Request, res: Response) => {
|
|||
res.send('Could not find user')
|
||||
return
|
||||
}
|
||||
await userManager.inviteUser(user)
|
||||
await sessionManager.inviteUser(user)
|
||||
res.status(200)
|
||||
res.send('Invitation sent to email')
|
||||
}
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
.App {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.App-logo {
|
||||
animation: App-logo-spin infinite 20s linear;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.App-header {
|
||||
background-color: #222;
|
||||
height: 150px;
|
||||
padding: 20px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.App-title {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.App-intro {
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
@keyframes App-logo-spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
|
@ -1,23 +1,15 @@
|
|||
import * as React from 'react';
|
||||
import {BrowserRouter as Router, Route} from 'react-router-dom';
|
||||
import './App.css';
|
||||
import CreateEvent from './CreateEvent';
|
||||
import Login from './Login'
|
||||
import logo from './logo.svg';
|
||||
import RequestMagicLink from './RequestMagicLink'
|
||||
|
||||
class App extends React.Component {
|
||||
public render() {
|
||||
return (
|
||||
<Router>
|
||||
<div className="App">
|
||||
<header className="App-header">
|
||||
<img src={logo} className="App-logo" alt="logo"/>
|
||||
<h1 className="App-title">Welcome to React</h1>
|
||||
</header>
|
||||
<div className="App-intro">
|
||||
<Route path="/login" component={Login}/>
|
||||
<Route path="/post" component={CreateEvent}/>
|
||||
</div>
|
||||
<div>
|
||||
<Route path="/login" component={RequestMagicLink}/>
|
||||
<Route path="/post" component={CreateEvent}/>
|
||||
</div>
|
||||
</Router>
|
||||
);
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
import axios from 'axios'
|
||||
import {Field, FieldProps, Form, Formik} from 'formik';
|
||||
import * as React from 'react';
|
||||
|
||||
const submitLogin = (loginRequest: LoginRequest) => {
|
||||
axios.post('/api/session', loginRequest)
|
||||
}
|
||||
|
||||
interface LoginRequest {
|
||||
email: string;
|
||||
}
|
||||
|
||||
const Login = () => (
|
||||
<div>
|
||||
<h1>Login</h1>
|
||||
<div>
|
||||
Please enter your email
|
||||
</div>
|
||||
<Formik onSubmit={submitLogin} initialValues={{email: ''}}>
|
||||
{
|
||||
() => (
|
||||
<Form>
|
||||
<Field name="email">
|
||||
{
|
||||
({ field }: FieldProps<string>) => <input {...field} />
|
||||
}
|
||||
</Field>
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
</Formik>
|
||||
</div>
|
||||
)
|
||||
export default Login
|
|
@ -0,0 +1,95 @@
|
|||
import axios from 'axios'
|
||||
import {Field, FieldProps, Form, Formik, FormikErrors, FormikProps} from 'formik';
|
||||
import * as React from 'react';
|
||||
import {RouteComponentProps, withRouter} from "react-router";
|
||||
import styled from 'styled-components';
|
||||
|
||||
const submitRequestToken = (loginRequest: SessionRequest) => {
|
||||
axios.post('/api/session', loginRequest)
|
||||
}
|
||||
|
||||
interface SessionRequest {
|
||||
email: string;
|
||||
}
|
||||
|
||||
interface Props extends RouteComponentProps {
|
||||
}
|
||||
|
||||
class RequestMagicLink extends React.Component<Props, {}> {
|
||||
|
||||
handleValidate(values: SessionRequest): FormikErrors<SessionRequest> {
|
||||
const errors: FormikErrors<SessionRequest> = {};
|
||||
// get a proper validator for this
|
||||
if (!(values && values.email && values.email.includes('@'))){
|
||||
errors.email = 'Must include valid email address'
|
||||
}
|
||||
return errors
|
||||
}
|
||||
|
||||
handleSubmit = async (values: SessionRequest) => {
|
||||
this.setState({
|
||||
loading: true,
|
||||
})
|
||||
let response
|
||||
try {
|
||||
response = await axios.post('/api/signin', values)
|
||||
} catch (e) {
|
||||
this.setState({
|
||||
error: e
|
||||
})
|
||||
return
|
||||
} finally {
|
||||
this.setState({
|
||||
loading: false
|
||||
})
|
||||
}
|
||||
|
||||
if (response.status === 200) {
|
||||
this.setState({
|
||||
error: null,
|
||||
invitationSent: true,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Login</h1>
|
||||
<MessageContainer>
|
||||
In order to just view the calendar you don't need to log in, you can simply go back to the calendar and browse
|
||||
the events. You only need a login if you have an event you would like to publish or manage. If you already have
|
||||
registered, simply enter your email below and you will get a magic link per email. Following the magic link will
|
||||
log you into this page. No password necessary.
|
||||
</MessageContainer>
|
||||
<Formik onSubmit={submitRequestToken} initialValues={{email: ''}} validateOnBlur={true} validate={this.handleValidate}>
|
||||
{
|
||||
(formikProps: FormikProps<SessionRequest>) => (
|
||||
<Form>
|
||||
<Field name="email">
|
||||
{
|
||||
({ field }: FieldProps<string>) => <input type="email" {...field} />
|
||||
}
|
||||
</Field>
|
||||
<Button disabled={!formikProps.isValid} type="submit">Request magic link</Button>
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
</Formik>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const MessageContainer = styled.div`
|
||||
max-width: 600px;
|
||||
margin-bottom: 24px;
|
||||
`
|
||||
const Button = styled.button`
|
||||
&[disabled] {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
`
|
||||
|
||||
export default withRouter(RequestMagicLink)
|
|
@ -0,0 +1,7 @@
|
|||
import * as React from 'react';
|
||||
|
||||
export default class Signup extends React.Component {
|
||||
render() {
|
||||
return <div>signup</div>
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: sans-serif;
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
import './index.css';
|
||||
import registerServiceWorker from './registerServiceWorker';
|
||||
|
||||
ReactDOM.render(
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
"member-access": false,
|
||||
"object-literal-sort-keys":false,
|
||||
"no-console": false,
|
||||
"interface-name" : false
|
||||
"interface-name" : false,
|
||||
"no-empty-interface" : false
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue