comunicconsole/src/ui/routes/LoginRoute.tsx

288 lines
5.8 KiB
TypeScript

/**
* Login route
*
* @author Pierre Hubert
*/
import {
Avatar,
Box,
Button,
Container,
CssBaseline,
List,
ListItem,
ListItemAvatar,
ListItemText,
Paper,
TextField,
Typography,
} from "@material-ui/core";
import { ErrorOutline, Lock, VpnKey } from "@material-ui/icons";
import LockOutlinedIcon from "@material-ui/icons/LockOutlined";
import React from "react";
import { AccountHelper, AuthOptions } from "../../helpers/AccountHelper";
import { input, matAlert } from "../widgets/DialogsProvider";
function ErrorGettingOptions() {
return (
<Paper
style={{
width: "100%",
padding: "10px",
marginTop: "10px",
display: "flex",
alignItems: "center",
}}
>
<ErrorOutline></ErrorOutline>
&nbsp; Could not get your auth options!
</Paper>
);
}
function Copyright() {
return (
<Typography variant="body2" color="textSecondary" align="center">
{"Copyright © "}
Comunic&nbsp;
{new Date().getFullYear()}
{"."}
</Typography>
);
}
interface LoginRouteState {
currEmail: string;
errorGettingAuthOptions: boolean;
authOptions?: AuthOptions;
}
export class LoginRoute extends React.Component<{}, LoginRouteState> {
constructor(props: any) {
super(props);
this.state = {
currEmail: "",
errorGettingAuthOptions: false,
authOptions: undefined,
};
this.handleChangedEmail = this.handleChangedEmail.bind(this);
this.handleSubmitEmail = this.handleSubmitEmail.bind(this);
}
get canSubmit(): boolean {
return this.state.currEmail.length > 4;
}
handleChangedEmail(e: React.ChangeEvent<HTMLInputElement>) {
this.setState({
currEmail: e.target.value,
errorGettingAuthOptions: false,
authOptions: undefined,
});
}
async handleSubmitEmail(e: React.ChangeEvent<any>) {
try {
e.preventDefault();
if (!this.canSubmit) return;
const options = await AccountHelper.getAuthOptions(
this.state.currEmail
);
this.setState({
errorGettingAuthOptions: false,
authOptions: options,
});
} catch (e) {
console.error("Failed to get auth options!", e);
this.setState({ errorGettingAuthOptions: true });
}
}
render() {
return (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "100%",
}}
>
<Container component="main" maxWidth="xs">
<CssBaseline />
<div
style={{
marginTop: "8px",
display: "flex",
flexDirection: "column",
alignItems: "center",
}}
>
<Avatar
style={{
margin: "1px",
backgroundColor: "pink",
}}
>
<LockOutlinedIcon />
</Avatar>
<Typography
component="h1"
variant="h5"
style={{ margin: "10px", marginBottom: "50px" }}
>
Comunic Console
</Typography>
<form
style={{
width: "100%", // Fix IE 11 issue.
marginTop: "1px",
}}
noValidate
onSubmit={this.handleSubmitEmail}
>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="email"
label="Email Address"
value={this.state.currEmail}
autoComplete="email"
onChange={this.handleChangedEmail}
autoFocus
/>
<Button
onClick={this.handleSubmitEmail}
fullWidth
variant="contained"
color="primary"
style={{
margin: "10px 0px 2px 0px",
}}
disabled={!this.canSubmit}
>
Sign In
</Button>
</form>
{/* Login error (if any) */}
{this.state.errorGettingAuthOptions ? (
ErrorGettingOptions()
) : (
<div></div>
)}
{/* Auth options */}
{this.state.authOptions ? (
<AuthOptionsWidget
email={this.state.currEmail}
options={this.state.authOptions}
></AuthOptionsWidget>
) : (
<div></div>
)}
</div>
<Box mt={8}>
<Copyright />
</Box>
</Container>
</div>
);
}
}
interface AuthOptionsWidgetProps {
email: string;
options: AuthOptions;
}
interface AuthOptionsWidgetState {}
class AuthOptionsWidget extends React.Component<
AuthOptionsWidgetProps,
AuthOptionsWidgetState
> {
constructor(props: Readonly<AuthOptionsWidgetProps>) {
super(props);
this.state = {};
this.loginWithResetToken = this.loginWithResetToken.bind(this);
this.loginWithSecurityKey = this.loginWithSecurityKey.bind(this);
}
async loginWithResetToken() {
try {
const token = await input({
label: "Reset token",
message: "Please specify here your token:",
minLength: 2,
title: "Login using access token",
});
await AccountHelper.authWithResetToken(this.props.email, token);
document.location.href = document.location.href + "";
} catch (e) {
console.error(e);
matAlert("Authentication failed!");
}
}
async loginWithSecurityKey(id: number) {
console.info(id);
}
render() {
return (
<Paper style={{ width: "100%", marginTop: "10px" }}>
<List style={{ width: "100%" }}>
{/* Password reset token */}
{this.props.options.reset_token ? (
<ListItem button onClick={this.loginWithResetToken}>
<ListItemAvatar>
<Avatar>
<Lock />
</Avatar>
</ListItemAvatar>
<ListItemText
primary="Reset token"
secondary="Sign in using a reset token"
/>
</ListItem>
) : (
<span></span>
)}
{this.props.options.keys.map((key) => (
<ListItem
button
onClick={() => this.loginWithSecurityKey(key.id)}
key={key.id}
>
<ListItemAvatar>
<Avatar>
<VpnKey />
</Avatar>
</ListItemAvatar>
<ListItemText
primary={key.name}
secondary="Sign in using this security key"
/>
</ListItem>
))}
</List>
</Paper>
);
}
}