feat: Replace Redirect with withRouter
This commit is contained in:
parent
286927663a
commit
1c15c6653f
@ -52,18 +52,10 @@ export function setUser(user: IUser) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LEVEL_SET_REVIEW = "LEVEL_SET_REVIEW";
|
|
||||||
export function setLevelReview(state: boolean) {
|
|
||||||
return {
|
|
||||||
type: LEVEL_SET_REVIEW,
|
|
||||||
state,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const LEVEL_SET_LOOKEDAT = "LEVEL_SET_LOOKEDAT";
|
export const LEVEL_SET_LOOKEDAT = "LEVEL_SET_LOOKEDAT";
|
||||||
export function setLevelLookedAt(ids: number[]) {
|
export function setLevelLookedAt(ids: number[]) {
|
||||||
return {
|
return {
|
||||||
type: LEVEL_SET_REVIEW,
|
type: LEVEL_SET_LOOKEDAT,
|
||||||
lookedAt: ids,
|
lookedAt: ids,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -10,7 +10,7 @@ import LoginPage from "../containers/LoginPage";
|
|||||||
import LevelListPage from "../containers/LevelList";
|
import LevelListPage from "../containers/LevelList";
|
||||||
import LevelPage from "../containers/LevelPage";
|
import LevelPage from "../containers/LevelPage";
|
||||||
import ReviewPage from "../containers/Review";
|
import ReviewPage from "../containers/Review";
|
||||||
import SummaryPage from "../pages/summary";
|
import SummaryPage from "../containers/SummaryPage";
|
||||||
import WelcomePage from "../pages/intro";
|
import WelcomePage from "../pages/intro";
|
||||||
|
|
||||||
import Drawer from "../containers/Drawer";
|
import Drawer from "../containers/Drawer";
|
||||||
@ -309,8 +309,7 @@ export default class Application extends React.Component<IProps> {
|
|||||||
isAuth={this.isAuthenticated}
|
isAuth={this.isAuthenticated}
|
||||||
path="/review/summary"
|
path="/review/summary"
|
||||||
component={() => {
|
component={() => {
|
||||||
return <SummaryPage
|
return <SummaryPage />
|
||||||
reviewMeta={this.getLastReview} />
|
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
</div >
|
</div >
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
setDrawerButton, setLevelReview, setLevelLookedAt,
|
setDrawerButton, setLevelLookedAt,
|
||||||
setLevelCurrentVocab, setLevelVocab, setLevelLoading
|
setLevelCurrentVocab, setLevelVocab, setLevelLoading
|
||||||
} from "../actions";
|
} from "../actions";
|
||||||
|
|
||||||
@ -10,12 +10,11 @@ import { IVocab } from "../models/vocab";
|
|||||||
import LevelPage from "../pages/level";
|
import LevelPage from "../pages/level";
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = state => {
|
||||||
const { currentVocab, lookedAt, toReview, vocab, loading } = state.level;
|
const { currentVocab, lookedAt, vocab, loading } = state.level;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
currentVocab,
|
currentVocab,
|
||||||
lookedAt,
|
lookedAt,
|
||||||
toReview,
|
|
||||||
vocab,
|
vocab,
|
||||||
loading,
|
loading,
|
||||||
};
|
};
|
||||||
@ -24,7 +23,6 @@ const mapStateToProps = state => {
|
|||||||
const mapDispatchToProps = dispatch => {
|
const mapDispatchToProps = dispatch => {
|
||||||
return {
|
return {
|
||||||
drawerButtonState: (state: boolean) => dispatch(setDrawerButton(state)),
|
drawerButtonState: (state: boolean) => dispatch(setDrawerButton(state)),
|
||||||
setReview: (state: boolean) => dispatch(setLevelReview(state)),
|
|
||||||
setLookedAt: (ids: number[]) => dispatch(setLevelLookedAt(ids)),
|
setLookedAt: (ids: number[]) => dispatch(setLevelLookedAt(ids)),
|
||||||
setCurrentVocab: (vocab: IVocab) => dispatch(setLevelCurrentVocab(vocab)),
|
setCurrentVocab: (vocab: IVocab) => dispatch(setLevelCurrentVocab(vocab)),
|
||||||
setVocab: (vocab: IVocab[]) => dispatch(setLevelVocab(vocab)),
|
setVocab: (vocab: IVocab[]) => dispatch(setLevelVocab(vocab)),
|
||||||
|
21
src/containers/SummaryPage.ts
Normal file
21
src/containers/SummaryPage.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { connect } from "react-redux";
|
||||||
|
|
||||||
|
import { setDrawerButton } from "../actions";
|
||||||
|
|
||||||
|
import SummaryPage from "../pages/summary";
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
return {
|
||||||
|
reviewMeta: state.lastReview,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
setDrawerButton: (state: boolean) => dispatch(setDrawerButton(state)),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const SummaryPageContainer = connect(mapStateToProps,
|
||||||
|
mapDispatchToProps)(SummaryPage);
|
||||||
|
export default SummaryPageContainer;
|
@ -10,7 +10,7 @@ import Card from "@material-ui/core/Card";
|
|||||||
import CardContent from "@material-ui/core/CardContent";
|
import CardContent from "@material-ui/core/CardContent";
|
||||||
import CircularProgress from "@material-ui/core/CircularProgress";
|
import CircularProgress from "@material-ui/core/CircularProgress";
|
||||||
|
|
||||||
import { Redirect } from "react-router-dom";
|
import { withRouter } from "react-router-dom";
|
||||||
|
|
||||||
import { IVocab } from "../models/vocab";
|
import { IVocab } from "../models/vocab";
|
||||||
|
|
||||||
@ -18,183 +18,170 @@ interface IProps {
|
|||||||
id: string;
|
id: string;
|
||||||
levelVocab: (id: string) => Promise<IVocab[]>;
|
levelVocab: (id: string) => Promise<IVocab[]>;
|
||||||
|
|
||||||
|
history: any;
|
||||||
|
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
setLoading: (state: boolean) => void;
|
setLoading: (state: boolean) => void;
|
||||||
vocab: IVocab[];
|
vocab: IVocab[];
|
||||||
setVocab: (vocab: IVocab[]) => void;
|
setVocab: (vocab: IVocab[]) => void;
|
||||||
setLookedAt: (ids: number[]) => void;
|
setLookedAt: (ids: number[]) => void;
|
||||||
setCurrentVocab: (vocab: IVocab) => void;
|
setCurrentVocab: (vocab: IVocab) => void;
|
||||||
setReview: (state: boolean) => void;
|
|
||||||
drawerButtonState: (state: boolean) => void;
|
drawerButtonState: (state: boolean) => void;
|
||||||
currentVocab: IVocab;
|
currentVocab: IVocab;
|
||||||
lookedAt: number[];
|
lookedAt: number[];
|
||||||
toReview: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class LevelPage extends React.Component<IProps> {
|
const LevelPageWithRouter = withRouter(
|
||||||
private uid = 0;
|
class LevelPage extends React.Component<IProps> {
|
||||||
// To prevent React from redrawing the vocabulary list and prematurely
|
private uid = 0;
|
||||||
// cancelling the animation
|
// To prevent React from redrawing the vocabulary list and prematurely
|
||||||
private uids: { [key: string]: string } = {};
|
// cancelling the animation
|
||||||
|
private uids: { [key: string]: string } = {};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
// Hide the drawer
|
// Hide the drawer
|
||||||
this.props.drawerButtonState(false);
|
this.props.drawerButtonState(false);
|
||||||
|
|
||||||
// Fetch the vocabulary
|
// Fetch the vocabulary
|
||||||
this.props.setLoading(true);
|
this.props.setLoading(true);
|
||||||
|
|
||||||
// TODO: Error handling
|
// TODO: Error handling
|
||||||
this.props.levelVocab(this.props.id).then(vocab => {
|
this.props.levelVocab(this.props.id).then(vocab => {
|
||||||
this.props.setVocab(vocab);
|
this.props.setVocab(vocab);
|
||||||
this.props.setCurrentVocab(vocab[0]);
|
this.props.setCurrentVocab(vocab[0]);
|
||||||
this.props.setLoading(false);
|
this.props.setLoading(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
genUID = (vocab: IVocab): string => {
|
|
||||||
const { grundform } = vocab.latin;
|
|
||||||
if (grundform in this.uids) {
|
|
||||||
return this.uids[grundform];
|
|
||||||
} else {
|
|
||||||
this.uids[grundform] = "LEVELPAGE" + this.uid++;
|
|
||||||
return this.uids[grundform];
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
renderVocabListItem = (vocab: IVocab): any => {
|
genUID = (vocab: IVocab): string => {
|
||||||
// Check if the vocab was already looked at
|
const { grundform } = vocab.latin;
|
||||||
const lookedAt = this.props.lookedAt.find((el) => el === vocab.id) || vocab.id === 0;
|
if (grundform in this.uids) {
|
||||||
|
return this.uids[grundform];
|
||||||
return <ListItem button key={this.genUID(vocab)} onClick={() => {
|
} else {
|
||||||
// Prevent the user from using too much memory by always clicking on the elements
|
this.uids[grundform] = "LEVELPAGE" + this.uid++;
|
||||||
// Show the clicked at vocab word
|
return this.uids[grundform];
|
||||||
|
}
|
||||||
this.props.setCurrentVocab(vocab);
|
|
||||||
this.props.setLookedAt(lookedAt ? (
|
|
||||||
this.props.lookedAt
|
|
||||||
) : this.props.lookedAt.concat(vocab.id));
|
|
||||||
}}>
|
|
||||||
<ListItemText>
|
|
||||||
{`${vocab.latin.grundform} ${lookedAt ? "✔" : ""}`}
|
|
||||||
</ListItemText>
|
|
||||||
</ListItem>;
|
|
||||||
}
|
|
||||||
|
|
||||||
toReview = () => {
|
|
||||||
const { vocab, lookedAt } = this.props;
|
|
||||||
// Only go to the review if all vocabulary item have been looked at
|
|
||||||
if (vocab.length === lookedAt.length) {
|
|
||||||
this.props.setReview(true);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
renderVocabListItem = (vocab: IVocab): any => {
|
||||||
if (this.props.loading) {
|
// Check if the vocab was already looked at
|
||||||
return <div>
|
const lookedAt = this.props.lookedAt.find((el) => el === vocab.id) || vocab.id === 0;
|
||||||
{/*
|
|
||||||
* This would be the case when the user presses the "to
|
return <ListItem button key={this.genUID(vocab)} onClick={() => {
|
||||||
* review" button. That is because we need the state of loading
|
// Prevent the user from using too much memory by always clicking on the elements
|
||||||
* to be true, when this page gets called
|
// Show the clicked at vocab word
|
||||||
* TODO:?
|
|
||||||
*/}
|
this.props.setCurrentVocab(vocab);
|
||||||
{
|
this.props.setLookedAt(lookedAt ? (
|
||||||
this.props.toReview ? (
|
this.props.lookedAt
|
||||||
<Redirect to={`/review/level/${this.props.id}`} />
|
) : this.props.lookedAt.concat(vocab.id));
|
||||||
) : undefined
|
}}>
|
||||||
}
|
<ListItemText>
|
||||||
<Grid
|
{`${vocab.latin.grundform} ${lookedAt ? "✔" : ""}`}
|
||||||
container
|
</ListItemText>
|
||||||
spacing={0}
|
</ListItem>;
|
||||||
direction="column"
|
}
|
||||||
alignItems="center"
|
|
||||||
justify="center"
|
toReview = () => {
|
||||||
style={{ minHeight: '100vh' }}>
|
const { vocab, lookedAt, id } = this.props;
|
||||||
<Grid item xs={12}>
|
// Only go to the review if all vocabulary item have been looked at
|
||||||
<Paper className="paper">
|
if (vocab.length === lookedAt.length) {
|
||||||
<Grid container direction="column" spacing={8}>
|
this.props.setLoading(true);
|
||||||
<CircularProgress />
|
this.props.history.push(`/review/level/${id}`);
|
||||||
</Grid>
|
}
|
||||||
</Paper>
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (this.props.loading) {
|
||||||
|
return <div>
|
||||||
|
<Grid
|
||||||
|
container
|
||||||
|
spacing={0}
|
||||||
|
direction="column"
|
||||||
|
alignItems="center"
|
||||||
|
justify="center"
|
||||||
|
style={{ minHeight: '100vh' }}>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Paper className="paper">
|
||||||
|
<Grid container direction="column" spacing={8}>
|
||||||
|
<CircularProgress />
|
||||||
|
</Grid>
|
||||||
|
</Paper>
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
|
||||||
|
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { currentVocab } = this.props;
|
const { currentVocab } = this.props;
|
||||||
return <div>
|
return <div>
|
||||||
<Grid container direction="row">
|
<Grid container direction="row">
|
||||||
<Grid item xs={3}>
|
<Grid item xs={3}>
|
||||||
<List>
|
<List>
|
||||||
{this.props.vocab
|
{this.props.vocab
|
||||||
.map(this.renderVocabListItem)}
|
.map(this.renderVocabListItem)}
|
||||||
{/* TODO*/}
|
<ListItem button onClick={this.toReview}>
|
||||||
<ListItem button onClick={this.toReview}>
|
<ListItemText>
|
||||||
<ListItemText>
|
Zur Übung
|
||||||
Zur Übung
|
|
||||||
</ListItemText>
|
</ListItemText>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
</Grid>
|
</Grid>
|
||||||
{
|
<Grid item lg={7} xs={9}>
|
||||||
this.props.toReview ? (
|
<Grid container direction="column">
|
||||||
<Redirect to={`/review/level/${this.props.id}`} />
|
<Grid item style={{ margin: 12 }}>
|
||||||
) : undefined
|
<Card>
|
||||||
}
|
<CardContent>
|
||||||
<Grid item lg={7} xs={9}>
|
<Typography gutterBottom variant="headline" component="h2">
|
||||||
<Grid container direction="column">
|
{currentVocab.latin.grundform}
|
||||||
<Grid item style={{ margin: 12 }}>
|
</Typography>
|
||||||
<Card>
|
<Typography gutterBottom variant="headline" component="h3">
|
||||||
<CardContent>
|
{currentVocab.german.join(", ")}
|
||||||
<Typography gutterBottom variant="headline" component="h2">
|
</Typography>
|
||||||
{currentVocab.latin.grundform}
|
{
|
||||||
</Typography>
|
currentVocab.hint ? (
|
||||||
<Typography gutterBottom variant="headline" component="h3">
|
<div style={{
|
||||||
{currentVocab.german.join(", ")}
|
border: "dashed",
|
||||||
</Typography>
|
borderColor: "red",
|
||||||
{
|
padding: 12,
|
||||||
currentVocab.hint ? (
|
}}>
|
||||||
<div style={{
|
<Typography variant="subheading" component="p">
|
||||||
border: "dashed",
|
<b>Tipp:</b>
|
||||||
borderColor: "red",
|
</Typography>
|
||||||
padding: 12,
|
<Typography variant="body2">
|
||||||
}}>
|
{currentVocab.hint}
|
||||||
<Typography variant="subheading" component="p">
|
</Typography>
|
||||||
<b>Tipp:</b>
|
</div>
|
||||||
</Typography>
|
) : undefined
|
||||||
<Typography variant="body2">
|
}
|
||||||
{currentVocab.hint}
|
{
|
||||||
</Typography>
|
currentVocab.mnemonic ? (
|
||||||
</div>
|
<div style={{
|
||||||
) : undefined
|
border: "dashed",
|
||||||
}
|
borderColor: "#f1c40f",
|
||||||
{
|
marginTop: 12,
|
||||||
currentVocab.mnemonic ? (
|
padding: 12,
|
||||||
<div style={{
|
}}>
|
||||||
border: "dashed",
|
<Typography variant="subheading" component="p">
|
||||||
borderColor: "#f1c40f",
|
<b>Eselsbrücke:</b>
|
||||||
marginTop: 12,
|
</Typography>
|
||||||
padding: 12,
|
<Typography variant="body2">
|
||||||
}}>
|
{currentVocab.mnemonic}
|
||||||
<Typography variant="subheading" component="p">
|
</Typography>
|
||||||
<b>Eselsbrücke:</b>
|
</div>
|
||||||
</Typography>
|
) : undefined
|
||||||
<Typography variant="body2">
|
}
|
||||||
{currentVocab.mnemonic}
|
</CardContent>
|
||||||
</Typography>
|
{/*TODO: Maybe "next" and "prev" buttons?*/}
|
||||||
</div>
|
</Card>
|
||||||
) : undefined
|
</Grid>
|
||||||
}
|
|
||||||
</CardContent>
|
|
||||||
{/*TODO: Maybe "next" and "prev" buttons?*/}
|
|
||||||
</Card>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</div>;
|
||||||
</div>;
|
}
|
||||||
}
|
}
|
||||||
};
|
);
|
||||||
|
export default LevelPageWithRouter;
|
||||||
|
@ -6,55 +6,51 @@ import Grid from "@material-ui/core/Grid";
|
|||||||
import Button from "@material-ui/core/Button";
|
import Button from "@material-ui/core/Button";
|
||||||
import SummaryTable from "../components/SummaryTable";
|
import SummaryTable from "../components/SummaryTable";
|
||||||
|
|
||||||
import { Redirect } from "react-router-dom";
|
import { withRouter } from "react-router-dom";
|
||||||
|
|
||||||
import { IReviewMetadata } from "../models/review";
|
import { IReviewMetadata } from "../models/review";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
reviewMeta: () => IReviewMetadata;
|
history: any;
|
||||||
|
|
||||||
|
reviewMeta: IReviewMetadata;
|
||||||
|
setDrawerButton: (state: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
// TODO: This stays at the default value
|
||||||
toDashboard: boolean;
|
const SummaryPageWithRouter = withRouter(
|
||||||
}
|
class SummaryPage extends React.Component<IProps> {
|
||||||
|
toDashboard = () => {
|
||||||
|
// Show the drawer button
|
||||||
|
this.props.setDrawerButton(true);
|
||||||
|
|
||||||
export default class SummaryPage extends React.Component<IProps, IState> {
|
// Go to the dashboard
|
||||||
constructor(props: any) {
|
this.props.history.push("/dashboard");
|
||||||
super(props);
|
}
|
||||||
|
|
||||||
this.state = {
|
render() {
|
||||||
toDashboard: false,
|
return <div>
|
||||||
};
|
<Grid
|
||||||
}
|
container
|
||||||
|
spacing={0}
|
||||||
render() {
|
direction="column"
|
||||||
return <div>
|
alignItems="center"
|
||||||
{
|
justify="center"
|
||||||
this.state.toDashboard ? (
|
style={{ minHeight: '100vh' }}>
|
||||||
<Redirect to="/dashboard" />
|
<Grid item xs={12}>
|
||||||
) : undefined
|
<Paper className="paper">
|
||||||
}
|
<Typography variant="title">Zusammenfassung</Typography>
|
||||||
<Grid
|
<Grid container direction="column">
|
||||||
container
|
<SummaryTable reviewMeta={() => this.props.reviewMeta} />
|
||||||
spacing={0}
|
<Button onClick={this.toDashboard}>
|
||||||
direction="column"
|
Zum Dashboard
|
||||||
alignItems="center"
|
|
||||||
justify="center"
|
|
||||||
style={{ minHeight: '100vh' }}>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Paper className="paper">
|
|
||||||
<Typography variant="title">Zusammenfassung</Typography>
|
|
||||||
<Grid container direction="column">
|
|
||||||
<SummaryTable reviewMeta={this.props.reviewMeta} />
|
|
||||||
<Button onClick={() => this.setState({
|
|
||||||
toDashboard: true,
|
|
||||||
})}>
|
|
||||||
Zum Dashboard
|
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</div>;
|
||||||
</div>;
|
}
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
|
export default SummaryPageWithRouter;
|
||||||
|
@ -26,7 +26,6 @@ interface IState {
|
|||||||
level: {
|
level: {
|
||||||
currentVocab: IVocab;
|
currentVocab: IVocab;
|
||||||
lookedAt: number[];
|
lookedAt: number[];
|
||||||
toReview: boolean;
|
|
||||||
vocab: IVocab[];
|
vocab: IVocab[];
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
};
|
};
|
||||||
@ -74,7 +73,6 @@ const initialState: IState = {
|
|||||||
level: {
|
level: {
|
||||||
currentVocab: {} as IVocab,
|
currentVocab: {} as IVocab,
|
||||||
lookedAt: [0],
|
lookedAt: [0],
|
||||||
toReview: false,
|
|
||||||
vocab: [],
|
vocab: [],
|
||||||
loading: true,
|
loading: true,
|
||||||
},
|
},
|
||||||
@ -137,15 +135,6 @@ export function LateinicusApp(state: IState = initialState, action: any) {
|
|||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
user: action.user,
|
user: action.user,
|
||||||
});
|
});
|
||||||
case Actions.LEVEL_SET_REVIEW:
|
|
||||||
return Object.assign({}, state, {
|
|
||||||
level: Object.assign({}, state.level, {
|
|
||||||
toReview: action.state,
|
|
||||||
// Make sure that we are in a "loading mode", when the page gets
|
|
||||||
// called the next time
|
|
||||||
loading: true,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
case Actions.LEVEL_SET_LOOKEDAT:
|
case Actions.LEVEL_SET_LOOKEDAT:
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
level: Object.assign({}, state.level, {
|
level: Object.assign({}, state.level, {
|
||||||
|
Reference in New Issue
Block a user