Added logout button functionality
This commit is contained in:
parent
8e6759f917
commit
05a8d7f090
@ -12,7 +12,7 @@
|
|||||||
"jquery": "^3.5.1",
|
"jquery": "^3.5.1",
|
||||||
"merge": "1.2.1",
|
"merge": "1.2.1",
|
||||||
"popper.js": "^1.16.0",
|
"popper.js": "^1.16.0",
|
||||||
"react": "16.11.0",
|
"react": "^16.11.0",
|
||||||
"react-dom": "16.11.0",
|
"react-dom": "16.11.0",
|
||||||
"react-redux": "7.1.1",
|
"react-redux": "7.1.1",
|
||||||
"react-router": "5.1.2",
|
"react-router": "5.1.2",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Box, Container, IconButton, Menu, MenuItem } from '@material-ui/core';
|
import { Box, Container, IconButton, Menu, MenuItem, MenuList, Paper, Grow, Popper } from '@material-ui/core';
|
||||||
import AccountCircle from '@material-ui/icons/AccountCircle';
|
import AccountCircle from '@material-ui/icons/AccountCircle';
|
||||||
import AppBar from '@material-ui/core/AppBar';
|
import AppBar from '@material-ui/core/AppBar';
|
||||||
import blue from '@material-ui/core/colors/blue';
|
import blue from '@material-ui/core/colors/blue';
|
||||||
@ -7,11 +7,12 @@ import { createMuiTheme, createStyles, makeStyles, Theme } from '@material-ui/co
|
|||||||
import Toolbar from '@material-ui/core/Toolbar';
|
import Toolbar from '@material-ui/core/Toolbar';
|
||||||
import Typography from '@material-ui/core/Typography';
|
import Typography from '@material-ui/core/Typography';
|
||||||
import { ThemeProvider } from '@material-ui/styles';
|
import { ThemeProvider } from '@material-ui/styles';
|
||||||
import React, { useState } from 'react';
|
import React, { useState, } from 'react';
|
||||||
import { BrowserRouter, NavLink, Redirect, Route, Switch } from 'react-router-dom';
|
import { BrowserRouter, NavLink, Redirect, Route, Switch, Link } from 'react-router-dom';
|
||||||
import BirdmapTitle from './common/components/BirdmapTitle';
|
import BirdmapTitle from './common/components/BirdmapTitle';
|
||||||
import Auth from './components/auth/Auth';
|
import Auth from './components/auth/Auth';
|
||||||
import AuthService from './components/auth/AuthService';
|
import AuthService from './components/auth/AuthService';
|
||||||
|
import { ClickAwayListener } from '@material-ui/core';
|
||||||
|
|
||||||
|
|
||||||
const theme = createMuiTheme({
|
const theme = createMuiTheme({
|
||||||
@ -87,17 +88,47 @@ const PrivateRoute = ({ component: Component, authenticated: Authenticated, ...r
|
|||||||
|
|
||||||
const DefaultLayout = ({ component: Component, authenticated: Authenticated, ...rest }: { [x: string]: any, component: any, authenticated: any }) => {
|
const DefaultLayout = ({ component: Component, authenticated: Authenticated, ...rest }: { [x: string]: any, component: any, authenticated: any }) => {
|
||||||
const classes = useDefaultLayoutStyles();
|
const classes = useDefaultLayoutStyles();
|
||||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
const [open, setOpen] = React.useState(false);
|
||||||
const open = Boolean(anchorEl);
|
const anchorRef = React.useRef<HTMLButtonElement>(null);
|
||||||
|
|
||||||
const handleMenu = (event: React.MouseEvent<HTMLElement>) => {
|
const handleToggle = () => {
|
||||||
setAnchorEl(event.currentTarget);
|
setOpen((prevOpen) => !prevOpen);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = (event: React.MouseEvent<EventTarget>) => {
|
||||||
setAnchorEl(null);
|
if (anchorRef.current && anchorRef.current.contains(event.target as HTMLElement)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleLogout = (event: React.MouseEvent<EventTarget>) => {
|
||||||
|
if (anchorRef.current && anchorRef.current.contains(event.target as HTMLElement)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthService.logout();
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
function handleListKeyDown(event: React.KeyboardEvent) {
|
||||||
|
if (event.key === 'Tab') {
|
||||||
|
event.preventDefault();
|
||||||
|
setOpen(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const prevOpen = React.useRef(open);
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (prevOpen.current === true && open === false) {
|
||||||
|
anchorRef.current!.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
prevOpen.current = open;
|
||||||
|
}, [open]);
|
||||||
|
|
||||||
|
|
||||||
const renderNavLinks = () => {
|
const renderNavLinks = () => {
|
||||||
return Authenticated
|
return Authenticated
|
||||||
? <Container className={classes.nav_menu}>
|
? <Container className={classes.nav_menu}>
|
||||||
@ -105,28 +136,28 @@ const DefaultLayout = ({ component: Component, authenticated: Authenticated, ...
|
|||||||
<NavLink exact to="/devices" className={classes.nav_menu_item} activeClassName={classes.nav_menu_item_active}>Devices</NavLink>
|
<NavLink exact to="/devices" className={classes.nav_menu_item} activeClassName={classes.nav_menu_item_active}>Devices</NavLink>
|
||||||
<NavLink exact to="/heatmap" className={classes.nav_menu_item} activeClassName={classes.nav_menu_item_active}>Heatmap</NavLink>
|
<NavLink exact to="/heatmap" className={classes.nav_menu_item} activeClassName={classes.nav_menu_item_active}>Heatmap</NavLink>
|
||||||
<IconButton className={classes.nav_menu_icon}
|
<IconButton className={classes.nav_menu_icon}
|
||||||
|
ref={anchorRef}
|
||||||
aria-haspopup="true"
|
aria-haspopup="true"
|
||||||
aria-controls="menu-appbar"
|
aria-controls={open ? 'menu-list-grow' : undefined}
|
||||||
aria-label="account of current user"
|
aria-label="account of current user"
|
||||||
onClick={handleMenu}>
|
onClick={handleToggle}>
|
||||||
<AccountCircle/>
|
<AccountCircle/>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<Menu
|
<Popper open={open} anchorEl={anchorRef.current} role={undefined} transition disablePortal>
|
||||||
id="menu-appbar"
|
{({ TransitionProps, placement }) => (
|
||||||
anchorEl={anchorEl}
|
<Grow
|
||||||
anchorOrigin={{
|
{...TransitionProps}
|
||||||
vertical: 'bottom',
|
style={{ transformOrigin: placement === 'bottom' ? 'center top' : 'center bottom' }}>
|
||||||
horizontal: 'right',
|
<Paper>
|
||||||
}}
|
<ClickAwayListener onClickAway={handleClose}>
|
||||||
keepMounted
|
<MenuList autoFocusItem={open} id="menu-list-grow" onKeyDown={handleListKeyDown}>
|
||||||
transformOrigin={{
|
<MenuItem onClick={handleLogout} component={Link} {...{ to: '/login' }}>Logout</MenuItem>
|
||||||
vertical: 'top',
|
</MenuList>
|
||||||
horizontal: 'right',
|
</ClickAwayListener>
|
||||||
}}
|
</Paper>
|
||||||
open={open}
|
</Grow>
|
||||||
onClose={handleClose}>
|
)}
|
||||||
<MenuItem onClick={handleClose}>Logout</MenuItem>
|
</Popper>
|
||||||
</Menu>
|
|
||||||
</Container>
|
</Container>
|
||||||
: null;
|
: null;
|
||||||
};
|
};
|
||||||
|
@ -5,6 +5,7 @@ import { makeStyles, createStyles, Theme } from '@material-ui/core/styles';
|
|||||||
import AuthService from './AuthService';
|
import AuthService from './AuthService';
|
||||||
|
|
||||||
export default function Auth(props: any) {
|
export default function Auth(props: any) {
|
||||||
|
props.onAuthenticated();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
@ -36,7 +37,6 @@ export default function Auth(props: any) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onLoginClicked = () => {
|
const onLoginClicked = () => {
|
||||||
setIsLoggingIn(true);
|
|
||||||
|
|
||||||
if (!username) {
|
if (!username) {
|
||||||
setShowError(true);
|
setShowError(true);
|
||||||
@ -52,6 +52,7 @@ export default function Auth(props: any) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setIsLoggingIn(true);
|
||||||
AuthService.login(username, password)
|
AuthService.login(username, password)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
props.onAuthenticated();
|
props.onAuthenticated();
|
||||||
@ -86,7 +87,7 @@ export default function Auth(props: any) {
|
|||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} >
|
<Grid item xs={12} >
|
||||||
<TextField label="Username" type="text" onChange={onUsernameChanged} />
|
<TextField autoFocus label="Username" type="text" onChange={onUsernameChanged} />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} >
|
<Grid item xs={12} >
|
||||||
<TextField label="Password" type="password" onChange={onPasswordChanged} onKeyPress={onPasswordKeyPress} />
|
<TextField label="Password" type="password" onChange={onPasswordChanged} onKeyPress={onPasswordKeyPress} />
|
||||||
|
@ -9,6 +9,10 @@ exports.default = {
|
|||||||
isAdmin: function () {
|
isAdmin: function () {
|
||||||
return sessionStorage.getItem('role') === 'Admin';
|
return sessionStorage.getItem('role') === 'Admin';
|
||||||
},
|
},
|
||||||
|
logout: function () {
|
||||||
|
sessionStorage.removeItem('user');
|
||||||
|
sessionStorage.removeItem('role');
|
||||||
|
},
|
||||||
login: function (username, password) {
|
login: function (username, password) {
|
||||||
var body = {
|
var body = {
|
||||||
username: username,
|
username: username,
|
||||||
|
@ -1 +1 @@
|
|||||||
{"version":3,"file":"AuthService.js","sourceRoot":"","sources":["AuthService.ts"],"names":[],"mappings":";;AAAA,wDAAmD;AAEnD,IAAM,SAAS,GAAG,uBAAuB,CAAC;AAE1C,kBAAe;IACX,eAAe;QACX,OAAO,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IACnD,CAAC;IAED,OAAO;QACH,OAAO,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC;IACtD,CAAC;IAED,KAAK,EAAL,UAAM,QAAgB,EAAE,QAAgB;QACpC,IAAI,IAAI,GAAG;YACP,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,QAAQ;SACrB,CAAC;QACF,IAAI,OAAO,GAAG;YACV,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACL,cAAc,EAAE,kBAAkB;aACrC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC7B,CAAC;QAEF,OAAO,qBAAW,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC;aAC7C,IAAI,CAAC,UAAA,QAAQ;YACV,cAAc,CAAC,OAAO,CAAC,MAAM,EAAK,QAAQ,CAAC,UAAU,SAAI,QAAQ,CAAC,YAAc,CAAC,CAAC;YAClF,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC9C,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;IACX,CAAC;CACJ,CAAA"}
|
{"version":3,"file":"AuthService.js","sourceRoot":"","sources":["AuthService.ts"],"names":[],"mappings":";;AAAA,wDAAmD;AAEnD,IAAM,SAAS,GAAG,uBAAuB,CAAC;AAE1C,kBAAe;IACX,eAAe;QACX,OAAO,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IACnD,CAAC;IAED,OAAO;QACH,OAAO,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC;IACtD,CAAC;IAED,MAAM;QACF,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAClC,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,EAAL,UAAM,QAAgB,EAAE,QAAgB;QACpC,IAAI,IAAI,GAAG;YACP,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,QAAQ;SACrB,CAAC;QACF,IAAI,OAAO,GAAG;YACV,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACL,cAAc,EAAE,kBAAkB;aACrC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC7B,CAAC;QAEF,OAAO,qBAAW,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC;aAC7C,IAAI,CAAC,UAAA,QAAQ;YACV,cAAc,CAAC,OAAO,CAAC,MAAM,EAAK,QAAQ,CAAC,UAAU,SAAI,QAAQ,CAAC,YAAc,CAAC,CAAC;YAClF,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC9C,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;IACX,CAAC;CACJ,CAAA"}
|
@ -11,6 +11,11 @@ export default {
|
|||||||
return sessionStorage.getItem('role') === 'Admin';
|
return sessionStorage.getItem('role') === 'Admin';
|
||||||
},
|
},
|
||||||
|
|
||||||
|
logout() {
|
||||||
|
sessionStorage.removeItem('user');
|
||||||
|
sessionStorage.removeItem('role');
|
||||||
|
},
|
||||||
|
|
||||||
login(username: string, password: string) {
|
login(username: string, password: string) {
|
||||||
let body = {
|
let body = {
|
||||||
username: username,
|
username: username,
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
},
|
},
|
||||||
"AllowedHosts": "*",
|
"AllowedHosts": "*",
|
||||||
"Secret": "7vj.3KW.hYE!}4u6",
|
"Secret": "7vj.3KW.hYE!}4u6",
|
||||||
"LocalDbConnectionString": "Data Source=DESKTOP-A6JQ6B5\\SQLEXPRESS;Initial Catalog=Birdmap;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
|
// "LocalDbConnectionString": "Data Source=DESKTOP-3600\\SQLEXPRESS;Initial Catalog=birdmap;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
|
||||||
|
"LocalDbConnectionString": "Data Source=DESKTOP-3600;Initial Catalog=birdmap;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
|
||||||
"Defaults": {
|
"Defaults": {
|
||||||
"Services": {
|
"Services": {
|
||||||
"Local Database": "https://localhost:44331/health",
|
"Local Database": "https://localhost:44331/health",
|
||||||
@ -18,7 +19,7 @@
|
|||||||
{
|
{
|
||||||
"Name": "admin",
|
"Name": "admin",
|
||||||
"Password": "pass",
|
"Password": "pass",
|
||||||
"Role": "Admin"
|
"Role": "Admin"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Name": "user",
|
"Name": "user",
|
||||||
|
Loading…
Reference in New Issue
Block a user