From 2f7e4682851cd17bb5318f6652de0ec7532ddc74 Mon Sep 17 00:00:00 2001 From: Alexander Polynomdivision Date: Tue, 18 Sep 2018 18:06:08 +0200 Subject: [PATCH] fix: Transition the drawer to redux --- package-lock.json | 37 ++++++++- package.json | 4 +- src/actions/index.ts | 15 ++++ src/components/Drawer.tsx | 146 ++++++++++++++++++++++++++++++++++ src/components/app.tsx | 163 +++----------------------------------- src/containers/Drawer.ts | 22 +++++ src/index.tsx | 13 ++- src/reducers/index.ts | 26 ++++++ 8 files changed, 268 insertions(+), 158 deletions(-) create mode 100644 src/actions/index.ts create mode 100644 src/components/Drawer.tsx create mode 100644 src/containers/Drawer.ts create mode 100644 src/reducers/index.ts diff --git a/package-lock.json b/package-lock.json index a6b163d..003281a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7880,8 +7880,12 @@ "lodash": { "version": "4.17.10", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", - "dev": true + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + }, + "lodash-es": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.11.tgz", + "integrity": "sha512-DHb1ub+rMjjrxqlB3H56/6MXtm1lSksDp2rA2cNWjG8mlDUYFhUj3Di2Zn5IwSU87xLv8tNIQ7sSwE/YOX/D/Q==" }, "lodash.clone": { "version": "4.5.0", @@ -10521,6 +10525,19 @@ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, + "react-redux": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.7.tgz", + "integrity": "sha512-5VI8EV5hdgNgyjfmWzBbdrqUkrVRKlyTKk1sGH3jzM2M2Mhj/seQgPXaz6gVAj2lz/nz688AdTqMO18Lr24Zhg==", + "requires": { + "hoist-non-react-statics": "^2.5.0", + "invariant": "^2.0.0", + "lodash": "^4.17.5", + "lodash-es": "^4.17.5", + "loose-envify": "^1.1.0", + "prop-types": "^15.6.0" + } + }, "react-router": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz", @@ -10691,6 +10708,22 @@ } } }, + "redux": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.0.tgz", + "integrity": "sha512-NnnHF0h0WVE/hXyrB6OlX67LYRuaf/rJcbWvnHHEPCF/Xa/AZpwhs/20WyqzQae5x4SD2F9nPObgBh2rxAgLiA==", + "requires": { + "loose-envify": "^1.1.0", + "symbol-observable": "^1.2.0" + }, + "dependencies": { + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" + } + } + }, "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", diff --git a/package.json b/package.json index 5a6531c..6fb447c 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,9 @@ "@material-ui/icons": "^2.0.3", "react": "^16.4.2", "react-dom": "^16.4.2", - "react-router-dom": "^4.3.1" + "react-redux": "^5.0.7", + "react-router-dom": "^4.3.1", + "redux": "^4.0.0" }, "devDependencies": { "@types/jest": "^23.3.2", diff --git a/src/actions/index.ts b/src/actions/index.ts new file mode 100644 index 0000000..9b0847b --- /dev/null +++ b/src/actions/index.ts @@ -0,0 +1,15 @@ +export const SET_DRAWER = "SET_DRAWER"; +export function setDrawer(state: boolean) { + return { + type: SET_DRAWER, + show: state, + }; +}; + +export const SET_DRAWER_BUTTON = "SET_DRAWER_BUTTON"; +export function setDrawerButton(state: boolean) { + return { + type: SET_DRAWER_BUTTON, + show: state, + }; +}; diff --git a/src/components/Drawer.tsx b/src/components/Drawer.tsx new file mode 100644 index 0000000..7a32dde --- /dev/null +++ b/src/components/Drawer.tsx @@ -0,0 +1,146 @@ +import * as React from "react"; + +import { Link } from "react-router-dom"; + +import AppBar from "@material-ui/core/AppBar"; +import Toolbar from "@material-ui/core/Toolbar"; +import Typography from "@material-ui/core/Typography"; +import IconButton from "@material-ui/core/IconButton"; +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"; +import MenuIcon from "@material-ui/icons/Menu"; +import SettingsIcon from "@material-ui/icons/Settings"; +import PersonIcon from "@material-ui/icons/Person"; +import InfoIcon from "@material-ui/icons/Info"; +import HomeIcon from "@material-ui/icons/Home"; +import BookIcon from "@material-ui/icons/Book"; +import ViewWeekIcon from "@material-ui/icons/ViewWeek"; + +interface IProps { + open: boolean; + showButton: boolean; + authenticated: boolean; + setDrawer: (state: boolean) => void; +}; + +export default class Drawer extends React.Component { + openDrawer = () => { + this.props.setDrawer(true); + } + closeDrawer = () => { + this.props.setDrawer(false); + } + + render() { + return ( +
+ + + { + (this.props.authenticated && this.props.showButton) ? ( + + + + ) : undefined + } + + Lateinicus + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Vokabeln üben + + + + + + + + Levelübersicht + + + + + + { + // Remove the auth token from the SessionStorage + // window.sessionStorage.removeItem("authKey"); + // TODO: Perform logout + }}> + + Abmelden + + + + + + window.location = "https://gitlab.com/Polynomdivision/Lateinicus/tree/master"}> + + + + + + + +
+ ); + } +}; diff --git a/src/components/app.tsx b/src/components/app.tsx index 1be85f1..60ea397 100644 --- a/src/components/app.tsx +++ b/src/components/app.tsx @@ -1,25 +1,6 @@ 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"; -import IconButton from "@material-ui/core/IconButton"; -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"; -import MenuIcon from "@material-ui/icons/Menu"; -import SettingsIcon from "@material-ui/icons/Settings"; -import PersonIcon from "@material-ui/icons/Person"; -import InfoIcon from "@material-ui/icons/Info"; -import HomeIcon from "@material-ui/icons/Home"; -import BookIcon from "@material-ui/icons/Book"; -import ViewWeekIcon from "@material-ui/icons/ViewWeek"; - -import { BrowserRouter, Route, Redirect, Link } from "react-router-dom"; +import { BrowserRouter, Route, Redirect } from "react-router-dom"; import AuthRoute from "../security/AuthRoute"; @@ -31,6 +12,8 @@ import ReviewPage from "../pages/review"; import SummaryPage from "../pages/summary"; import WelcomePage from "../pages/intro"; +import Drawer from "../containers/Drawer"; + import { BACKEND_URL } from "../config"; import { ILevel } from "../models/level"; @@ -39,20 +22,10 @@ import { IVocab, VocabType } from "../models/vocab"; import { IReviewMetadata, ReviewType } from "../models/review"; import { IUser } from "../models/user"; -interface IState { - loggedIn: boolean; - user: IUser | {}; - - lastReview: IReviewMetadata; - - drawerOpen: boolean; - showDrawerButton: boolean; -} - // TODO: Replace the sessionStorage with localStorage? // 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<{}> { constructor(props: any) { super(props); @@ -61,20 +34,6 @@ export default class Application extends React.Component<{}, IState> { // TODO const loggedIn = authKey !== null; - // TODO: Fetch the last review - this.state = { - loggedIn, - user: {}, - - lastReview: { - correct: 0, - wrong: 0, - }, - - drawerOpen: false, - showDrawerButton: true, - }; - this.login = this.login.bind(this); this.isAuthenticated = this.isAuthenticated.bind(this); } @@ -101,7 +60,8 @@ export default class Application extends React.Component<{}, IState> { console.log("STUB: Application::getLastReview"); // TODO: Actually fetch this - return this.state.lastReview; + // TODO: Stub + return {} as IReviewMetadata; } setLastReview = (meta: IReviewMetadata) => { @@ -256,7 +216,8 @@ export default class Application extends React.Component<{}, IState> { // Checks whether the user is logged in isAuthenticated() { // TODO: Security? - return this.state.loggedIn === true; + // TODO: Implement + return true; } closeDrawer = () => { @@ -279,113 +240,7 @@ export default class Application extends React.Component<{}, IState> { return
- - - { - (this.isAuthenticated() && this.state.showDrawerButton) ? ( - this.setState({ drawerOpen: true })}> - - - ) : undefined - } - - Lateinicus - - - - this.setState({ drawerOpen: false, })} - onOpen={() => this.setState({ drawerOpen: true })}> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Vokabeln üben - - - - - - - - Levelübersicht - - - - - - { - // 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, - }); - }}> - - Abmelden - - - - - - window.location = "https://gitlab.com/Polynomdivision/Lateinicus/tree/master"}> - - - - - - - - +
} /> { diff --git a/src/containers/Drawer.ts b/src/containers/Drawer.ts new file mode 100644 index 0000000..b7ef1d5 --- /dev/null +++ b/src/containers/Drawer.ts @@ -0,0 +1,22 @@ +import { connect } from "react-redux"; + +import { setDrawer } from "../actions"; + +import Drawer from "../components/Drawer"; + +const mapStateToProps = state => { + return { + open: state.drawer, + authenticated: state.authenticated, + showButton: state.drawerButton, + }; +}; +const mapDispatchToProps = dispatch => { + return { + setDrawer: (show: boolean) => dispatch(setDrawer(show)), + }; +}; + +const DrawerContainer = connect(mapStateToProps, + mapDispatchToProps)(Drawer); +export default DrawerContainer; diff --git a/src/index.tsx b/src/index.tsx index 4787bdd..71b467a 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,6 +1,17 @@ import * as React from "react"; import * as ReactDOM from "react-dom"; +import { createStore } from "redux"; +import { Provider } from "react-redux"; + +import { LateinicusApp } from "./reducers"; + import Application from "./components/app"; -ReactDOM.render(, document.getElementById("app")); +const store = createStore(LateinicusApp); + +ReactDOM.render(( + + + +), document.getElementById("app")); diff --git a/src/reducers/index.ts b/src/reducers/index.ts new file mode 100644 index 0000000..310999e --- /dev/null +++ b/src/reducers/index.ts @@ -0,0 +1,26 @@ +import * as Actions from "../actions"; + +const initialState = { + // Show the drawer? + drawer: false, + // Should we show the button to open the drawer? + drawerButton: true, + // Is the user authenticated? + // TODO: Set this to false + authenticated: true, +}; + +export function LateinicusApp(state = initialState, action: any) { + switch (action.type) { + case Actions.SET_DRAWER: + return Object.assign({}, state, { + drawer: action.show, + }); + case Actions.SET_DRAWER_BUTTON: + return Object.assign({}, state, { + drawerButton: action.show, + }); + default: + return state; + } +};