2018-08-24 17:03:08 +00:00
|
|
|
import * as React from "react";
|
|
|
|
|
|
|
|
import AppBar from "@material-ui/core/AppBar";
|
|
|
|
import Toolbar from "@material-ui/core/Toolbar";
|
|
|
|
import Typography from "@material-ui/core/Typography";
|
2018-08-26 15:19:55 +00:00
|
|
|
import IconButton from "@material-ui/core/IconButton";
|
2018-08-26 17:27:21 +00:00
|
|
|
import SwipeableDrawer from "@material-ui/core/SwipeableDrawer";
|
|
|
|
import List from "@material-ui/core/List";
|
|
|
|
import ListItem from "@material-ui/core/ListItem";
|
|
|
|
import ListItemIcon from "@material-ui/core/ListItemIcon";
|
|
|
|
import ListItemText from "@material-ui/core/ListItemText";
|
|
|
|
import Divider from "@material-ui/core/Divider";
|
|
|
|
import Avatar from "@material-ui/core/Avatar";
|
2018-08-26 15:19:55 +00:00
|
|
|
import MenuIcon from "@material-ui/icons/Menu";
|
2018-08-26 17:27:21 +00:00
|
|
|
import SettingsIcon from "@material-ui/icons/Settings";
|
|
|
|
import PersonIcon from "@material-ui/icons/Person";
|
|
|
|
import InfoIcon from "@material-ui/icons/Info";
|
2018-08-24 17:03:08 +00:00
|
|
|
|
2018-08-26 14:23:48 +00:00
|
|
|
import { BrowserRouter, Route, Redirect } from "react-router-dom";
|
|
|
|
|
|
|
|
import AuthRoute from "../security/AuthRoute";
|
|
|
|
|
|
|
|
import Dashboard from "../pages/dashboard";
|
2018-08-24 17:03:08 +00:00
|
|
|
import LoginPage from "../pages/login";
|
2018-09-06 18:13:29 +00:00
|
|
|
import LevelListPage from "../pages/levelList";
|
2018-09-06 18:05:21 +00:00
|
|
|
import LevelPage from "../pages/level";
|
2018-08-26 14:23:48 +00:00
|
|
|
|
2018-09-06 18:13:29 +00:00
|
|
|
import { ILevel } from "../models/level";
|
2018-09-06 18:05:21 +00:00
|
|
|
import { IVocab } from "../models/vocab";
|
2018-08-24 17:03:08 +00:00
|
|
|
|
|
|
|
interface IState {
|
|
|
|
loggedIn: boolean;
|
2018-08-26 17:27:21 +00:00
|
|
|
|
|
|
|
drawerOpen: boolean;
|
2018-08-24 17:03:08 +00:00
|
|
|
}
|
|
|
|
|
2018-09-06 18:22:41 +00:00
|
|
|
// TODO: Replace the sessionStorage with localStorage
|
2018-08-24 17:03:08 +00:00
|
|
|
export default class Application extends React.Component<{}, IState> {
|
|
|
|
constructor(props: any) {
|
|
|
|
super(props);
|
|
|
|
|
2018-09-06 18:22:41 +00:00
|
|
|
// Load a key from the SessionStorage
|
|
|
|
const authKey = window.sessionStorage.getItem("authKey") || null;
|
|
|
|
// TODO
|
|
|
|
const loggedIn = authKey !== null;
|
|
|
|
|
2018-08-24 17:03:08 +00:00
|
|
|
this.state = {
|
2018-09-06 18:22:41 +00:00
|
|
|
loggedIn,
|
2018-09-06 18:05:21 +00:00
|
|
|
drawerOpen: false,
|
2018-08-24 17:03:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
this.login = this.login.bind(this);
|
2018-08-26 14:23:48 +00:00
|
|
|
this.isAuthenticated = this.isAuthenticated.bind(this);
|
|
|
|
}
|
|
|
|
|
2018-09-06 18:13:29 +00:00
|
|
|
getLevels(): ILevel[] {
|
2018-08-26 15:12:07 +00:00
|
|
|
// TODO: Actually fetch them from somewhere
|
2018-09-06 18:13:29 +00:00
|
|
|
const levels = [{
|
2018-08-26 14:23:48 +00:00
|
|
|
name: "Der Bauer auf dem Feld",
|
|
|
|
desc: "So fängt alles an: Du bist ein einfacher Bauer und musst dich die Karriereleiter mit deinen freshen Latein-Skills hinaufarbeiten",
|
|
|
|
level: 1,
|
|
|
|
done: true,
|
|
|
|
}, {
|
|
|
|
name: "???",
|
|
|
|
desc: "Warum schreibe ich überhaupt was?dsd dddddddddddddddddddddd",
|
|
|
|
level: 2,
|
|
|
|
done: false,
|
|
|
|
}];
|
|
|
|
|
2018-09-06 18:13:29 +00:00
|
|
|
return levels;
|
2018-08-24 17:03:08 +00:00
|
|
|
}
|
|
|
|
|
2018-09-06 18:05:21 +00:00
|
|
|
getLearners(): ILearner[] {
|
2018-08-26 15:12:07 +00:00
|
|
|
return [{
|
|
|
|
username: "Polynomdivision",
|
|
|
|
level: 5,
|
|
|
|
score: 400,
|
|
|
|
}, {
|
|
|
|
username: "Polynomdivision2",
|
|
|
|
level: 3,
|
|
|
|
score: 500,
|
|
|
|
}, {
|
|
|
|
username: "Der eine Typ",
|
|
|
|
level: 7,
|
|
|
|
score: 100,
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
|
2018-09-06 18:13:29 +00:00
|
|
|
getNextLevel(): ILevel {
|
2018-09-06 18:05:21 +00:00
|
|
|
// TODO: Actually fetch data
|
|
|
|
return {
|
|
|
|
name: "???",
|
|
|
|
desc: "Warum schreibe ich überhaupt was?dsd dddddddddddddddddddddd",
|
|
|
|
level: 2,
|
|
|
|
done: false,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
getLevelVocab(id: string): IVocab[] {
|
|
|
|
// TODO: Actually implement this
|
|
|
|
// TODO: Don't fetch this when it was already fetched once.
|
|
|
|
return [{
|
|
|
|
latin: "Veni",
|
|
|
|
german: "<Wortbedeutung>",
|
|
|
|
id: 0
|
|
|
|
}, {
|
|
|
|
latin: "Vidi",
|
|
|
|
german: "<Wortbedeutung>",
|
|
|
|
id: 1
|
|
|
|
}, {
|
|
|
|
latin: "Vici",
|
|
|
|
german: "<Wortbedeutung>",
|
|
|
|
hint: "Wird \"Viki\" und nicht \"Vichi\" ausgesprochen",
|
|
|
|
mnemonic: "Merk dir das Wort mit Caesars berühmten Worten: \"Veni Vidi Vici\"; Er kam, sah und siegte",
|
|
|
|
id: 2
|
|
|
|
}] as IVocab[];
|
|
|
|
}
|
|
|
|
|
2018-08-24 17:03:08 +00:00
|
|
|
login(username: string, password: string): Promise<boolean> {
|
|
|
|
return new Promise((res, rej) => {
|
|
|
|
// TODO
|
2018-08-26 14:23:48 +00:00
|
|
|
this.setState({
|
|
|
|
loggedIn: true
|
|
|
|
});
|
2018-08-24 17:03:08 +00:00
|
|
|
res();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-08-26 14:23:48 +00:00
|
|
|
// Checks whether the user is logged in
|
|
|
|
isAuthenticated() {
|
|
|
|
// TODO: Security?
|
|
|
|
return this.state.loggedIn === true;
|
|
|
|
}
|
|
|
|
|
2018-08-24 17:03:08 +00:00
|
|
|
render() {
|
2018-08-26 14:23:48 +00:00
|
|
|
return <BrowserRouter
|
2018-08-26 17:27:21 +00:00
|
|
|
basename="/app/">
|
2018-08-26 14:23:48 +00:00
|
|
|
<div className="flex">
|
|
|
|
<AppBar position="static">
|
|
|
|
<Toolbar>
|
2018-08-26 15:19:55 +00:00
|
|
|
{
|
|
|
|
this.isAuthenticated() ? (
|
2018-08-26 17:27:21 +00:00
|
|
|
<IconButton
|
|
|
|
color="inherit"
|
|
|
|
onClick={() => this.setState({ drawerOpen: true })}>
|
2018-08-26 15:19:55 +00:00
|
|
|
<MenuIcon />
|
|
|
|
</IconButton>
|
|
|
|
) : undefined
|
|
|
|
}
|
2018-08-26 14:23:48 +00:00
|
|
|
<Typography className="flex" variant="title" color="inherit">
|
|
|
|
Lateinicus
|
2018-08-24 17:03:08 +00:00
|
|
|
</Typography>
|
2018-08-26 14:23:48 +00:00
|
|
|
</Toolbar>
|
|
|
|
</AppBar>
|
2018-08-26 17:27:21 +00:00
|
|
|
<SwipeableDrawer
|
|
|
|
anchor="left"
|
|
|
|
open={this.state.drawerOpen}
|
|
|
|
onClose={() => this.setState({ drawerOpen: false, })}
|
|
|
|
onOpen={() => this.setState({ drawerOpen: true })}>
|
|
|
|
<List component="nav">
|
|
|
|
<ListItem>
|
|
|
|
{/* TODO: Replace with the actual username */}
|
|
|
|
<Avatar alt="{Username}" style={{ width: 80, height: 80 }} src="https://avatarfiles.alphacoders.com/105/105250.jpg" />
|
|
|
|
<ListItemText primary="{Username}" />
|
|
|
|
</ListItem>
|
|
|
|
|
|
|
|
<Divider />
|
|
|
|
|
|
|
|
<ListItem button>
|
|
|
|
<ListItemIcon>
|
|
|
|
<PersonIcon />
|
|
|
|
</ListItemIcon>
|
|
|
|
<ListItemText primary="Profil" />
|
|
|
|
</ListItem>
|
|
|
|
<ListItem button>
|
|
|
|
<ListItemIcon>
|
|
|
|
<SettingsIcon />
|
|
|
|
</ListItemIcon>
|
|
|
|
<ListItemText primary="Einstellungen" />
|
|
|
|
</ListItem>
|
|
|
|
|
|
|
|
<Divider />
|
|
|
|
|
|
|
|
<ListItem button>
|
|
|
|
<ListItemText primary="Widerholen" />
|
|
|
|
</ListItem>
|
|
|
|
<ListItem button>
|
2018-09-06 18:05:21 +00:00
|
|
|
<ListItemText>
|
|
|
|
Levelübersicht
|
|
|
|
</ListItemText>
|
2018-08-26 17:27:21 +00:00
|
|
|
</ListItem>
|
|
|
|
|
|
|
|
<Divider />
|
|
|
|
|
2018-09-06 18:22:41 +00:00
|
|
|
<ListItem button onClick={() => {
|
|
|
|
// Remove the auth token from the SessionStorage
|
|
|
|
window.sessionStorage.removeItem("authKey");
|
|
|
|
// Set the loggedIn State to false
|
|
|
|
this.setState({
|
|
|
|
loggedIn: false,
|
|
|
|
// In case the drawer was open
|
|
|
|
drawerOpen: false,
|
|
|
|
});
|
|
|
|
}}>
|
|
|
|
<ListItemText>
|
|
|
|
Abmelden
|
|
|
|
</ListItemText>
|
|
|
|
</ListItem>
|
|
|
|
|
|
|
|
<Divider />
|
|
|
|
|
2018-08-26 17:27:21 +00:00
|
|
|
<ListItem button onClick={() => window.location = "https://gitlab.com/Polynomdivision/Lateinicus/tree/master"}>
|
|
|
|
<ListItemIcon>
|
|
|
|
<InfoIcon />
|
|
|
|
</ListItemIcon>
|
|
|
|
<ListItemText primary="Über" />
|
|
|
|
</ListItem>
|
|
|
|
</List>
|
|
|
|
</SwipeableDrawer>
|
2018-08-24 17:03:08 +00:00
|
|
|
|
2018-08-26 14:23:48 +00:00
|
|
|
<div className="content">
|
|
|
|
<Route exact path="/" component={() => <Redirect to="/login" />} />
|
|
|
|
<Route exact path="/login" component={() => {
|
|
|
|
return <LoginPage loggedIn={this.state.loggedIn} login={this.login} />
|
|
|
|
}} />
|
2018-08-26 15:12:07 +00:00
|
|
|
<AuthRoute
|
|
|
|
isAuth={this.isAuthenticated}
|
|
|
|
path="/dashboard"
|
2018-09-06 18:13:29 +00:00
|
|
|
component={() => <Dashboard nextLevel={this.getNextLevel} learners={this.getLearners()} />} />
|
2018-08-26 15:12:07 +00:00
|
|
|
<AuthRoute
|
|
|
|
isAuth={this.isAuthenticated}
|
2018-09-06 18:05:21 +00:00
|
|
|
path="/levelList"
|
2018-09-06 18:13:29 +00:00
|
|
|
component={() => <LevelListPage levels={this.getLevels()} />} />
|
2018-09-06 18:05:21 +00:00
|
|
|
{/*We cannot use AuthRoute here, because match is undefined otherwise*/}
|
|
|
|
<Route
|
|
|
|
path="/level/:id"
|
|
|
|
component={({ match }) => {
|
|
|
|
if (this.isAuthenticated()) {
|
|
|
|
return <LevelPage id={match.params.id} levelVocab={this.getLevelVocab} />;
|
|
|
|
} else {
|
|
|
|
return <Redirect to="/login" />;
|
|
|
|
}
|
|
|
|
}} />
|
2018-08-26 14:23:48 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</BrowserRouter>;
|
2018-08-24 17:03:08 +00:00
|
|
|
}
|
|
|
|
};
|