From 3702af03e254f0cdb753aa56b5d69e905315f678 Mon Sep 17 00:00:00 2001 From: Albin Henriksson <albhe428@student.liu.se> Date: Tue, 2 Mar 2021 10:08:54 +0000 Subject: [PATCH] Resolve "Add admin-view" --- .gitignore | 1 + .vscode/tasks.json | 2 +- client/package-lock.json | 8 + client/package.json | 6 +- client/src/App.tsx | 14 +- client/src/Main.tsx | 17 +++ client/src/components/AdminView.css | 10 ++ client/src/components/AdminView.test.tsx | 12 ++ client/src/components/AdminView.tsx | 139 ++++++++++++++++++ .../components/CompetitionManager.test.tsx | 7 + client/src/components/CompetitionManager.tsx | 12 ++ client/src/components/Login.test.tsx | 7 + client/src/components/Login.tsx | 12 +- client/src/components/Regions.test.tsx | 7 + client/src/components/Regions.tsx | 12 ++ 15 files changed, 244 insertions(+), 22 deletions(-) create mode 100644 client/src/Main.tsx create mode 100644 client/src/components/AdminView.css create mode 100644 client/src/components/AdminView.test.tsx create mode 100644 client/src/components/AdminView.tsx create mode 100644 client/src/components/CompetitionManager.test.tsx create mode 100644 client/src/components/CompetitionManager.tsx create mode 100644 client/src/components/Login.test.tsx create mode 100644 client/src/components/Regions.test.tsx create mode 100644 client/src/components/Regions.tsx diff --git a/.gitignore b/.gitignore index 2dcb4d9f..51cc949e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ __pycache__ *.db */env *.coverage +*/coverage htmlcov .pytest_cache \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 22158c9d..df39c205 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -17,7 +17,7 @@ "type": "npm", "script": "test:coverage:html", "path": "client/", - "group": "test", + "group": "build", "problemMatcher": [], }, { diff --git a/client/package-lock.json b/client/package-lock.json index 67ccc686..d6c2bd5b 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1753,6 +1753,14 @@ "react-transition-group": "^4.4.0" } }, + "@material-ui/icons": { + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.2.tgz", + "integrity": "sha512-fQNsKX2TxBmqIGJCSi3tGTO/gZ+eJgWmMJkgDiOfyNaunNaxcklJQFaFogYcFl0qFuaEz1qaXYXboa/bUXVSOQ==", + "requires": { + "@babel/runtime": "^7.4.4" + } + }, "@material-ui/lab": { "version": "4.0.0-alpha.57", "resolved": "https://registry.npmjs.org/@material-ui/lab/-/lab-4.0.0-alpha.57.tgz", diff --git a/client/package.json b/client/package.json index 4fcc3e71..4d2df9fc 100644 --- a/client/package.json +++ b/client/package.json @@ -4,6 +4,7 @@ "private": true, "dependencies": { "@material-ui/core": "^4.11.3", + "@material-ui/icons": "^4.11.2", "@material-ui/lab": "^4.0.0-alpha.57", "@testing-library/jest-dom": "^5.11.9", "@testing-library/react": "^11.2.5", @@ -63,11 +64,12 @@ "collectCoverageFrom": [ "src/**/*.{js,jsx,tsx,ts}", "!src/index.tsx", - "!src/reportWebVitals.ts" + "!src/reportWebVitals.ts", + "!src/components/TestConnection.tsx" ], "coverageReporters": [ "text", - "cobertura", + "cobertura", "html" ] }, diff --git a/client/src/App.tsx b/client/src/App.tsx index 2df0f43f..1e8c051e 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,8 +1,6 @@ import React from 'react' -import { BrowserRouter, Route, Switch } from 'react-router-dom' import './App.css' -import LoginForm from './components/Login' -import TestConnection from './components/TestConnection' +import Main from './Main' const App: React.FC = () => { return ( @@ -11,15 +9,7 @@ const App: React.FC = () => { rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" /> - <h1>Application</h1> - <TestConnection /> - <BrowserRouter> - <Switch> - <Route path="/"> - <LoginForm /> - </Route> - </Switch> - </BrowserRouter> + <Main /> </div> ) } diff --git a/client/src/Main.tsx b/client/src/Main.tsx new file mode 100644 index 00000000..a44422fd --- /dev/null +++ b/client/src/Main.tsx @@ -0,0 +1,17 @@ +import React from 'react' +import { BrowserRouter, Route, Switch } from 'react-router-dom' +import AdminView from './components/AdminView' +import LoginForm from './components/Login' + +const Main = () => { + return ( + <BrowserRouter> + <Switch> + <Route exact path="/" component={LoginForm} /> + <Route path="/admin" component={AdminView} /> + </Switch> + </BrowserRouter> + ) +} + +export default Main diff --git a/client/src/components/AdminView.css b/client/src/components/AdminView.css new file mode 100644 index 00000000..1ad0b7ee --- /dev/null +++ b/client/src/components/AdminView.css @@ -0,0 +1,10 @@ +.background { + background: linear-gradient(to top, #efd5ff 0%, #3d55b3 100%); + height: 100%; +} + +.top-bar { + display:flex; + justify-content: space-between; + align-items: flex-start; +} \ No newline at end of file diff --git a/client/src/components/AdminView.test.tsx b/client/src/components/AdminView.test.tsx new file mode 100644 index 00000000..cdc46049 --- /dev/null +++ b/client/src/components/AdminView.test.tsx @@ -0,0 +1,12 @@ +import { render } from '@testing-library/react' +import React from 'react' +import { BrowserRouter } from 'react-router-dom' +import AdminView from './AdminView' + +it('renders admin view', () => { + render( + <BrowserRouter> + <AdminView /> + </BrowserRouter> + ) +}) diff --git a/client/src/components/AdminView.tsx b/client/src/components/AdminView.tsx new file mode 100644 index 00000000..54551b64 --- /dev/null +++ b/client/src/components/AdminView.tsx @@ -0,0 +1,139 @@ +import { + AppBar, + Button, + CssBaseline, + Divider, + Drawer, + List, + ListItem, + ListItemIcon, + ListItemText, + Toolbar, + Typography +} from '@material-ui/core' +import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import DashboardIcon from '@material-ui/icons/Dashboard' +import MailIcon from '@material-ui/icons/Mail' +import React from 'react' +import { Link, Route, Switch, useRouteMatch } from 'react-router-dom' +import './AdminView.css' +import CompetitionManager from './CompetitionManager' +import Regions from './Regions' + +const drawerWidth = 240 +const menuItems = ['Startsida', 'Regioner', 'Användare', 'Tävlingshanterare'] + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + root: { + display: 'flex' + }, + appBar: { + width: `calc(100% - ${drawerWidth}px)`, + marginLeft: drawerWidth + }, + drawer: { + width: drawerWidth, + flexShrink: 0, + marginRight: drawerWidth + }, + drawerPaper: { + width: drawerWidth + }, + // necessary for content to be below app bar + toolbar: theme.mixins.toolbar, + content: { + flexGrow: 1, + backgroundColor: theme.palette.background.default, + paddingLeft: theme.spacing(30) + } + }) +) + +const AdminView: React.FC = (props) => { + const classes = useStyles() + const [openIndex, setOpenIndex] = React.useState(0) + const match = useRouteMatch() + console.log(match) + const { path, url } = match + return ( + <div className={classes.root}> + <CssBaseline /> + <AppBar position="fixed" className={classes.appBar}> + <Toolbar> + <Typography variant="h5" noWrap> + {menuItems[openIndex]} + </Typography> + </Toolbar> + </AppBar> + <Drawer + className={(classes.drawer, 'background')} + variant="permanent" + classes={{ + paper: classes.drawerPaper + }} + anchor="left" + > + <div className="background"> + <div className={classes.toolbar} /> + <Divider /> + <List> + {menuItems.map((text, index) => ( + <ListItem + button + component={Link} + key={text} + to={`${url}/${text.toLowerCase()}`} + selected={index === openIndex} + onClick={() => setOpenIndex(index)} + > + <ListItemIcon> + {text === 'Dashboard' ? <DashboardIcon /> : <MailIcon />} + </ListItemIcon> + <ListItemText primary={text} /> + </ListItem> + ))} + </List> + <Divider /> + <List> + <ListItem> + <Button + component={Link} + to="/" + type="submit" + fullWidth + variant="contained" + color="primary" + > + Logga ut + </Button> + </ListItem> + </List> + </div> + </Drawer> + <main className={classes.content}> + <div className={classes.toolbar} /> + <Switch> + <Route exact path={[path, `${path}/startsida`]}> + <Typography variant="h1" noWrap> + Startsida + </Typography> + </Route> + <Route path={`${path}/regioner`}> + <Regions /> + </Route> + <Route path={`${path}/användare`}> + <Typography variant="h1" noWrap> + Användare + </Typography> + </Route> + <Route path={`${path}/tävlingshanterare`}> + <CompetitionManager /> + </Route> + </Switch> + </main> + </div> + ) +} + +export default AdminView diff --git a/client/src/components/CompetitionManager.test.tsx b/client/src/components/CompetitionManager.test.tsx new file mode 100644 index 00000000..b7156f68 --- /dev/null +++ b/client/src/components/CompetitionManager.test.tsx @@ -0,0 +1,7 @@ +import { render } from '@testing-library/react' +import React from 'react' +import CompetitionManager from './CompetitionManager' + +it('renders competition manager', () => { + render(<CompetitionManager />) +}) diff --git a/client/src/components/CompetitionManager.tsx b/client/src/components/CompetitionManager.tsx new file mode 100644 index 00000000..2d140fa3 --- /dev/null +++ b/client/src/components/CompetitionManager.tsx @@ -0,0 +1,12 @@ +import { Typography } from '@material-ui/core' +import React from 'react' + +const CompetitionManager: React.FC = (props) => { + return ( + <Typography variant="h1" noWrap> + Tävlingshanterare + </Typography> + ) +} + +export default CompetitionManager diff --git a/client/src/components/Login.test.tsx b/client/src/components/Login.test.tsx new file mode 100644 index 00000000..12a6c79c --- /dev/null +++ b/client/src/components/Login.test.tsx @@ -0,0 +1,7 @@ +import { render } from '@testing-library/react' +import React from 'react' +import LoginForm from './Login' + +it('renders login form', () => { + render(<LoginForm />) +}) diff --git a/client/src/components/Login.tsx b/client/src/components/Login.tsx index 75123ff3..91af9b78 100644 --- a/client/src/components/Login.tsx +++ b/client/src/components/Login.tsx @@ -28,12 +28,10 @@ interface ServerResponse { const schema: Yup.SchemaOf<LoginFormModel> = Yup.object({ model: Yup.object() .shape({ - email: Yup.string() - .email('Email not valid') - .required('Email is required'), + email: Yup.string().email('Email inte giltig').required('Email krävs'), password: Yup.string() - .required('Password is required') - .min(6, 'Password must be at least 6 characters') + .required('Lösenord krävs') + .min(6, 'Lösenord måste vara minst 6 karaktärer') }) .required(), error: Yup.string().optional() @@ -69,7 +67,7 @@ const LoginForm: React.FC = (props) => { {(formik) => ( <form onSubmit={formik.handleSubmit} className="login-form"> <TextField - label="Email Address" + label="Email Adress" name="model.email" helperText={ formik.touched.model?.email ? formik.errors.model?.email : '' @@ -80,7 +78,7 @@ const LoginForm: React.FC = (props) => { margin="normal" /> <TextField - label="Password" + label="Lösenord" name="model.password" type="password" helperText={ diff --git a/client/src/components/Regions.test.tsx b/client/src/components/Regions.test.tsx new file mode 100644 index 00000000..6f7fb873 --- /dev/null +++ b/client/src/components/Regions.test.tsx @@ -0,0 +1,7 @@ +import { render } from '@testing-library/react' +import React from 'react' +import Regions from './Regions' + +it('renders regions', () => { + render(<Regions />) +}) diff --git a/client/src/components/Regions.tsx b/client/src/components/Regions.tsx new file mode 100644 index 00000000..f40c8344 --- /dev/null +++ b/client/src/components/Regions.tsx @@ -0,0 +1,12 @@ +import Typography from '@material-ui/core/Typography' +import React from 'react' + +const Regions: React.FC = (props) => { + return ( + <Typography variant="h1" noWrap> + Regions + </Typography> + ) +} + +export default Regions -- GitLab