feat: Remove the login stub
This commit is contained in:
parent
1dfdd2f409
commit
2cadcec370
@ -31,13 +31,17 @@ import ReviewPage from "../pages/review";
|
|||||||
import SummaryPage from "../pages/summary";
|
import SummaryPage from "../pages/summary";
|
||||||
import WelcomePage from "../pages/intro";
|
import WelcomePage from "../pages/intro";
|
||||||
|
|
||||||
|
import { BACKEND_URL } from "../config";
|
||||||
|
|
||||||
import { ILevel } from "../models/level";
|
import { ILevel } from "../models/level";
|
||||||
import { ILearner } from "../models/learner";
|
import { ILearner } from "../models/learner";
|
||||||
import { IVocab, VocabType } from "../models/vocab";
|
import { IVocab, VocabType } from "../models/vocab";
|
||||||
import { IReviewMetadata, ReviewType } from "../models/review";
|
import { IReviewMetadata, ReviewType } from "../models/review";
|
||||||
|
import { IUser } from "../models/user";
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
loggedIn: boolean;
|
loggedIn: boolean;
|
||||||
|
user: IUser | {};
|
||||||
|
|
||||||
lastReview: IReviewMetadata;
|
lastReview: IReviewMetadata;
|
||||||
|
|
||||||
@ -47,18 +51,20 @@ interface IState {
|
|||||||
|
|
||||||
// TODO: Replace the sessionStorage with localStorage?
|
// TODO: Replace the sessionStorage with localStorage?
|
||||||
// TODO: Cache API-Calls
|
// TODO: Cache API-Calls
|
||||||
|
// TODO: When mounting without a login, check if the sessionToken is still valid
|
||||||
export default class Application extends React.Component<{}, IState> {
|
export default class Application extends React.Component<{}, IState> {
|
||||||
constructor(props: any) {
|
constructor(props: any) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
// Load a key from the SessionStorage
|
// Load a key from the SessionStorage
|
||||||
const authKey = window.sessionStorage.getItem("authKey") || null;
|
const authKey = window.sessionStorage.getItem("sessionToken") || null;
|
||||||
// TODO
|
// TODO
|
||||||
const loggedIn = authKey !== null;
|
const loggedIn = authKey !== null;
|
||||||
|
|
||||||
// TODO: Fetch the last review
|
// TODO: Fetch the last review
|
||||||
this.state = {
|
this.state = {
|
||||||
loggedIn,
|
loggedIn,
|
||||||
|
user: {},
|
||||||
|
|
||||||
lastReview: {
|
lastReview: {
|
||||||
correct: 0,
|
correct: 0,
|
||||||
@ -99,6 +105,8 @@ export default class Application extends React.Component<{}, IState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setLastReview = (meta: IReviewMetadata) => {
|
setLastReview = (meta: IReviewMetadata) => {
|
||||||
|
console.log("STUB: Application::setLastReview");
|
||||||
|
|
||||||
// TODO: Send this to the server
|
// TODO: Send this to the server
|
||||||
this.setState({
|
this.setState({
|
||||||
lastReview: meta,
|
lastReview: meta,
|
||||||
@ -216,16 +224,32 @@ export default class Application extends React.Component<{}, IState> {
|
|||||||
} */] as IVocab[];
|
} */] as IVocab[];
|
||||||
}
|
}
|
||||||
|
|
||||||
login(username: string, password: string): Promise<boolean> {
|
login(username: string, password: string): Promise<IUser | {}> {
|
||||||
console.log("STUB: Application::login");
|
|
||||||
|
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
// TODO: First login? Redirect to /welcome
|
// TODO: First login? Redirect to /welcome
|
||||||
// TODO
|
fetch(`${BACKEND_URL}/login`, {
|
||||||
this.setState({
|
method: "POST",
|
||||||
loggedIn: true
|
headers: new Headers({
|
||||||
});
|
'Content-Type': "application/json",
|
||||||
res();
|
}),
|
||||||
|
body: JSON.stringify({
|
||||||
|
// NOTE: We will force HTTPS and hash using pbkdf2 on the
|
||||||
|
// server
|
||||||
|
username: username,
|
||||||
|
hash: password,
|
||||||
|
}),
|
||||||
|
}).then(data => data.json())
|
||||||
|
.then((resp) => {
|
||||||
|
if (resp.error === "0") {
|
||||||
|
this.setState({
|
||||||
|
loggedIn: true,
|
||||||
|
user: resp.data,
|
||||||
|
});
|
||||||
|
res(resp.data);
|
||||||
|
} else {
|
||||||
|
rej({});
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,9 +302,8 @@ export default class Application extends React.Component<{}, IState> {
|
|||||||
onOpen={() => this.setState({ drawerOpen: true })}>
|
onOpen={() => this.setState({ drawerOpen: true })}>
|
||||||
<List component="nav">
|
<List component="nav">
|
||||||
<ListItem>
|
<ListItem>
|
||||||
{/* TODO: Replace with the actual username */}
|
|
||||||
<Avatar alt="{Username}" style={{ width: 80, height: 80 }} src="https://avatarfiles.alphacoders.com/105/105250.jpg" />
|
<Avatar alt="{Username}" style={{ width: 80, height: 80 }} src="https://avatarfiles.alphacoders.com/105/105250.jpg" />
|
||||||
<ListItemText primary="{Username}" />
|
<ListItemText primary={this.state.user.username} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
// Maximum distance from the answer to be still considered correct
|
// Maximum distance from the answer to be still considered correct
|
||||||
export const LEVENSHTEIN_MAX_DISTANCE = 2;
|
export const LEVENSHTEIN_MAX_DISTANCE = 2;
|
||||||
|
|
||||||
|
export const BACKEND_URL = "http://127.0.0.1:8080";
|
||||||
|
7
src/models/user.ts
Normal file
7
src/models/user.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export interface IUser {
|
||||||
|
username: string;
|
||||||
|
uid: string;
|
||||||
|
showWelcome: boolean;
|
||||||
|
|
||||||
|
sessionToken: string;
|
||||||
|
};
|
@ -10,8 +10,10 @@ import Snackbar from "@material-ui/core/Snackbar";
|
|||||||
|
|
||||||
import { Redirect } from "react-router-dom";
|
import { Redirect } from "react-router-dom";
|
||||||
|
|
||||||
|
import { IUser } from "../models/user";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
login: (username: string, password: string) => Promise<boolean>;
|
login: (username: string, password: string) => Promise<IUser | {}>;
|
||||||
loggedIn: boolean;
|
loggedIn: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,14 +27,14 @@ interface IState {
|
|||||||
open: boolean;
|
open: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class LoginPage extends React.Component<{}, IState> {
|
export default class LoginPage extends React.Component<IProps, IState> {
|
||||||
constructor(props: any) {
|
constructor(props: any) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
username: "",
|
username: "",
|
||||||
password: "",
|
password: "",
|
||||||
loading: false;
|
loading: false,
|
||||||
snack: "",
|
snack: "",
|
||||||
open: false,
|
open: false,
|
||||||
};
|
};
|
||||||
@ -50,12 +52,12 @@ export default class LoginPage extends React.Component<{}, IState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
performLogin() {
|
performLogin() {
|
||||||
const load = (loading) => {
|
const load = (loading: boolean) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading
|
loading
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const showSnackbar = (msg) => {
|
const showSnackbar = (msg: string) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
open: true,
|
open: true,
|
||||||
snack: msg,
|
snack: msg,
|
||||||
@ -65,9 +67,10 @@ export default class LoginPage extends React.Component<{}, IState> {
|
|||||||
load(true);
|
load(true);
|
||||||
|
|
||||||
const { username, password } = this.state;
|
const { username, password } = this.state;
|
||||||
this.props.login(username, password).then((res) => {
|
console.log(this.state);
|
||||||
|
this.props.login(username, password).then((res: IUser) => {
|
||||||
// Set the session key
|
// Set the session key
|
||||||
window.sessionStorage.setItem("authKey", "test123");
|
window.sessionStorage.setItem("sessionToken", res.sessionToken);
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
load(false);
|
load(false);
|
||||||
showSnackbar("Failed to log in");
|
showSnackbar("Failed to log in");
|
||||||
@ -94,13 +97,15 @@ export default class LoginPage extends React.Component<{}, IState> {
|
|||||||
<Grid item>
|
<Grid item>
|
||||||
<TextField
|
<TextField
|
||||||
label="Username"
|
label="Username"
|
||||||
onChange={(ev) => this.update("username")} />
|
onChange={this.update("username")}
|
||||||
|
value={this.state.username} />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item>
|
<Grid item>
|
||||||
<TextField
|
<TextField
|
||||||
label="Passwort"
|
label="Passwort"
|
||||||
type="password"
|
type="password"
|
||||||
onChange={(ev) => this.update("password")} />
|
value={this.state.password}
|
||||||
|
onChange={this.update("password")} />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item>
|
<Grid item>
|
||||||
<Button
|
<Button
|
||||||
|
@ -7,6 +7,7 @@ import Grid from "@material-ui/core/Grid";
|
|||||||
import Button from "@material-ui/core/Button";
|
import Button from "@material-ui/core/Button";
|
||||||
import Typography from "@material-ui/core/Typography";
|
import Typography from "@material-ui/core/Typography";
|
||||||
import Popover from "@material-ui/core/Popover";
|
import Popover from "@material-ui/core/Popover";
|
||||||
|
import LinearProgress from "@material-ui/core/LinearProgress";
|
||||||
|
|
||||||
import { Redirect } from "react-router-dom";
|
import { Redirect } from "react-router-dom";
|
||||||
|
|
||||||
@ -177,6 +178,8 @@ export default class ReviewPage extends React.Component<IProps, IState> {
|
|||||||
render() {
|
render() {
|
||||||
const { question, qtype } = this.state.current;
|
const { question, qtype } = this.state.current;
|
||||||
const questionTitle = `${question} (${reviewQTypeToStr(qtype)})`;
|
const questionTitle = `${question} (${reviewQTypeToStr(qtype)})`;
|
||||||
|
// TODO:
|
||||||
|
const progress = 50;
|
||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
{
|
{
|
||||||
@ -204,6 +207,9 @@ export default class ReviewPage extends React.Component<IProps, IState> {
|
|||||||
if (ev.key === "Enter")
|
if (ev.key === "Enter")
|
||||||
this.checkInput();
|
this.checkInput();
|
||||||
}} />
|
}} />
|
||||||
|
<LinearProgress
|
||||||
|
variant="determinate"
|
||||||
|
value={progress} />
|
||||||
<Popover
|
<Popover
|
||||||
open={this.state.popoverOpen}
|
open={this.state.popoverOpen}
|
||||||
anchorOrigin={{
|
anchorOrigin={{
|
||||||
|
Reference in New Issue
Block a user