| @@ -11,18 +11,18 @@ | |||||
| z-index: 9999; | z-index: 9999; | ||||
| border-bottom: 3px solid #0C489E; | border-bottom: 3px solid #0C489E; | ||||
| } | } | ||||
| #navbar{ | |||||
| #navbar div{ | |||||
| display: flex; | display: flex; | ||||
| align-items: center; | align-items: center; | ||||
| justify-content: center; | justify-content: center; | ||||
| } | } | ||||
| #navbar li{ | |||||
| #navbar div li{ | |||||
| list-style: none; | list-style: none; | ||||
| padding: 0 20px; | padding: 0 20px; | ||||
| position: relative; | position: relative; | ||||
| } | } | ||||
| #navbar li a{ | |||||
| #navbar div li a{ | |||||
| text-decoration: none; | text-decoration: none; | ||||
| font-size: 1.5rem; | font-size: 1.5rem; | ||||
| font-weight: 600; | font-weight: 600; | ||||
| @@ -30,11 +30,11 @@ | |||||
| color: black; | color: black; | ||||
| transition: 0.3s ease-in-out; | transition: 0.3s ease-in-out; | ||||
| } | } | ||||
| #navbar li a:hover{ | |||||
| #navbar div li a:hover{ | |||||
| color: #0C489E; | color: #0C489E; | ||||
| } | } | ||||
| #navbar li a:hover::after, | |||||
| #navbar li a:focus::after{ | |||||
| #navbar div li a:hover::after, | |||||
| #navbar div li a:focus::after{ | |||||
| content: ""; | content: ""; | ||||
| width: 60%; | width: 60%; | ||||
| height: 2px; | height: 2px; | ||||
| @@ -62,14 +62,27 @@ | |||||
| text-align: center; | text-align: center; | ||||
| } | } | ||||
| #sidebar{ | #sidebar{ | ||||
| font-size: 1.3rem; | |||||
| font-weight: 600; | |||||
| font-family: 微軟正黑體; | |||||
| } | |||||
| #sidebartop{ | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| padding: 0; | |||||
| display: flex; | |||||
| } | |||||
| #sidebarbottom{ | |||||
| align-items: center; | align-items: center; | ||||
| justify-content: center; | justify-content: center; | ||||
| padding: 0; | padding: 0; | ||||
| display: flex; | |||||
| } | } | ||||
| #sidebar li{ | #sidebar li{ | ||||
| list-style: none; | list-style: none; | ||||
| padding: 0 20px; | padding: 0 20px; | ||||
| position: relative; | position: relative; | ||||
| text-align: left; | |||||
| } | } | ||||
| #sidebar li a{ | #sidebar li a{ | ||||
| text-decoration: none; | text-decoration: none; | ||||
| @@ -1,4 +1,4 @@ | |||||
| import useJwt from 'auth/jwt/coreUseJwt' | |||||
| import useJwt from 'auth/jwt/coreUseJwt'; | |||||
| /** | /** | ||||
| * Return if user is logged in | * Return if user is logged in | ||||
| @@ -6,16 +6,16 @@ import useJwt from 'auth/jwt/coreUseJwt' | |||||
| * e.g. If you are using cookies to store the application please update this function | * e.g. If you are using cookies to store the application please update this function | ||||
| */ | */ | ||||
| // eslint-disable-next-line arrow-body-style | // eslint-disable-next-line arrow-body-style | ||||
| export const hostname = "localhost" | |||||
| const hostPort = "8080" | |||||
| export const hostPath = `http://${hostname}:${hostPort}` | |||||
| export const apiPath = `${hostPath}/api` | |||||
| export const hostname = 'localhost'; | |||||
| const hostPort = '8090'; | |||||
| export const hostPath = `http://${hostname}:${hostPort}`; | |||||
| export const apiPath = `${hostPath}/api`; | |||||
| export const isUserLoggedIn = () => { | export const isUserLoggedIn = () => { | ||||
| return localStorage.getItem('userData') && localStorage.getItem(useJwt.jwtConfig.storageTokenKeyName) | |||||
| } | |||||
| return localStorage.getItem('userData') && localStorage.getItem(useJwt.jwtConfig.storageTokenKeyName); | |||||
| }; | |||||
| export const getUserData = () => JSON.parse(localStorage.getItem('userData')) | |||||
| export const getUserData = () => JSON.parse(localStorage.getItem('userData')); | |||||
| /** | /** | ||||
| * This function is used for demo purpose route navigation | * This function is used for demo purpose route navigation | ||||
| @@ -25,9 +25,9 @@ export const getUserData = () => JSON.parse(localStorage.getItem('userData')) | |||||
| * NOTE: If you have different pages to navigate based on user ability then this function can be useful. However, you need to update it. | * NOTE: If you have different pages to navigate based on user ability then this function can be useful. However, you need to update it. | ||||
| * @param {String} userRole Role of user | * @param {String} userRole Role of user | ||||
| */ | */ | ||||
| export const getHomeRouteForLoggedInUser = userRole => { | |||||
| if (userRole === 'admin') return '/' | |||||
| if (userRole === 'user') return '/' | |||||
| if (userRole === 'client') return {name: 'access-control'} | |||||
| return {name: 'auth-login'} | |||||
| } | |||||
| export const getHomeRouteForLoggedInUser = (userRole) => { | |||||
| if (userRole === 'admin') return '/'; | |||||
| if (userRole === 'user') return '/'; | |||||
| if (userRole === 'client') return { name: 'access-control' }; | |||||
| return { name: 'auth-login' }; | |||||
| }; | |||||
| @@ -2,6 +2,9 @@ import PropTypes from 'prop-types'; | |||||
| import React | import React | ||||
| ,{useState} | ,{useState} | ||||
| from 'react'; | from 'react'; | ||||
| import {useDispatch} from "react-redux"; | |||||
| import {useNavigate} from "react-router-dom"; | |||||
| // material-ui | // material-ui | ||||
| // import { useTheme } from '@mui/material/styles'; | // import { useTheme } from '@mui/material/styles'; | ||||
| import { | import { | ||||
| @@ -28,7 +31,7 @@ import { | |||||
| // useMediaQuery | // useMediaQuery | ||||
| } from '@mui/material'; | } from '@mui/material'; | ||||
| import MenuIcon from '@mui/icons-material/Menu'; | |||||
| import MenuIcon from '@mui/icons-material/Menu'; | |||||
| // project import | // project import | ||||
| // import AppBarStyled from './AppBarStyled'; | // import AppBarStyled from './AppBarStyled'; | ||||
| // import HeaderContent from './HeaderContent'; | // import HeaderContent from './HeaderContent'; | ||||
| @@ -37,6 +40,7 @@ import MobileLogo from 'components/MobileLogo'; | |||||
| import Profile from './HeaderContent/Profile'; | import Profile from './HeaderContent/Profile'; | ||||
| import "assets/style/navbarStyles.css"; | import "assets/style/navbarStyles.css"; | ||||
| import {isUserLoggedIn} from "utils/Utils"; | import {isUserLoggedIn} from "utils/Utils"; | ||||
| import { handleLogoutFunction } from 'auth/index'; | |||||
| // assets | // assets | ||||
| // import { MenuFoldOutlined,MenuOutlined } from '@ant-design/icons'; | // import { MenuFoldOutlined,MenuOutlined } from '@ant-design/icons'; | ||||
| @@ -50,29 +54,71 @@ const drawerWidth = 240; | |||||
| function Header(props) { | function Header(props) { | ||||
| const { window } = props; | const { window } = props; | ||||
| const [mobileOpen, setMobileOpen] = useState(false); | const [mobileOpen, setMobileOpen] = useState(false); | ||||
| const dispatch = useDispatch() | |||||
| const navigate = useNavigate() | |||||
| const handleDrawerToggle = () => { | const handleDrawerToggle = () => { | ||||
| setMobileOpen((prevState) => !prevState); | setMobileOpen((prevState) => !prevState); | ||||
| }; | }; | ||||
| const handleLogout = async () => { | |||||
| dispatch(handleLogoutFunction()); | |||||
| //await handleLogoutFunction(); | |||||
| navigate('/login'); | |||||
| }; | |||||
| const loginContent = ( | |||||
| <div> | |||||
| <li> | |||||
| <Link className="userSearchview" to='/userSearchview'>User</Link> | |||||
| </li> | |||||
| <li> | |||||
| <Link className="usergroupSearchview" to='/usergroupSearchview'>User Group</Link> | |||||
| </li> | |||||
| </div> | |||||
| ); | |||||
| const logoutContent = ( | |||||
| <div> | |||||
| <li> | |||||
| <Link className="login" to='/login'>登入</Link> | |||||
| </li> | |||||
| <li> | |||||
| <Link className="register" to='/register'>申請</Link> | |||||
| </li> | |||||
| </div> | |||||
| ); | |||||
| const drawer = ( | const drawer = ( | ||||
| <Box onClick={handleDrawerToggle} sx={{ textAlign: 'center' }}> | |||||
| <Typography variant="h6" sx={{ my: 2 }}> | |||||
| PNSPS | |||||
| </Typography> | |||||
| <Divider /> | |||||
| <ul id="sidebar"> | |||||
| <li> | |||||
| <Link className="login" to='/login'>登入</Link> | |||||
| </li> | |||||
| <li> | |||||
| <Link className="register" to='/register'>申請</Link> | |||||
| </li> | |||||
| </ul> | |||||
| <Divider /> | |||||
| {} | |||||
| <Profile /> | |||||
| </Box> | |||||
| isUserLoggedIn() ? | |||||
| <Stack id="sidebar" direction="column" justifyContent="center" alignItems="center" onClick={handleDrawerToggle} sx={{ textAlign: 'center' }}> | |||||
| <Typography variant="h6" sx={{ my: 2 }}> | |||||
| PNSPS | |||||
| </Typography> | |||||
| <Divider /> | |||||
| <loginContent></loginContent> | |||||
| <ul id="sidebartop"> | |||||
| {loginContent} | |||||
| </ul> | |||||
| <Divider /> | |||||
| <ul id="sidebarbottom"> | |||||
| <li> | |||||
| <Link className="logout" onClick={handleLogout}>登出</Link> | |||||
| </li> | |||||
| </ul> | |||||
| </Stack> | |||||
| : | |||||
| <Stack id="sidebar" direction="column" justifyContent="center" alignItems="center" onClick={handleDrawerToggle} sx={{ textAlign: 'center' }}> | |||||
| <Typography variant="h6" sx={{ my: 2 }}> | |||||
| PNSPS | |||||
| </Typography> | |||||
| <Divider /> | |||||
| <loginContent></loginContent> | |||||
| <ul id="sidebartop"> | |||||
| {logoutContent} | |||||
| </ul> | |||||
| <Divider /> | |||||
| </Stack> | |||||
| ); | ); | ||||
| const container = window !== undefined ? () => window().document.body : undefined; | const container = window !== undefined ? () => window().document.body : undefined; | ||||
| @@ -113,12 +159,7 @@ function Header(props) { | |||||
| spacing={1} | spacing={1} | ||||
| > | > | ||||
| <ul id="navbar" width="100%" > | <ul id="navbar" width="100%" > | ||||
| <li> | |||||
| <Link className="userSearchview" to='/userSearchview'>User</Link> | |||||
| </li> | |||||
| <li> | |||||
| <Link className="usergroupSearchview" to='/usergroupSearchview'>User Group</Link> | |||||
| </li> | |||||
| {loginContent} | |||||
| </ul> | </ul> | ||||
| <Profile /> | <Profile /> | ||||
| </Stack> | </Stack> | ||||
| @@ -178,12 +219,7 @@ function Header(props) { | |||||
| spacing={1} | spacing={1} | ||||
| > | > | ||||
| <ul id="navbar" width="100%" > | <ul id="navbar" width="100%" > | ||||
| <li> | |||||
| <Link className="login" to='/login'>登入</Link> | |||||
| </li> | |||||
| <li> | |||||
| <Link className="register" to='/register'>申請</Link> | |||||
| </li> | |||||
| {logoutContent} | |||||
| </ul> | </ul> | ||||
| {/* <Profile /> */} | {/* <Profile /> */} | ||||
| </Stack> | </Stack> | ||||
| @@ -26,6 +26,9 @@ import { Formik } from 'formik'; | |||||
| //import FirebaseSocial from './FirebaseSocial'; | //import FirebaseSocial from './FirebaseSocial'; | ||||
| import AnimateButton from 'components/@extended/AnimateButton'; | import AnimateButton from 'components/@extended/AnimateButton'; | ||||
| //import {AbilityContext} from "@src/utility/context/Can" | //import {AbilityContext} from "@src/utility/context/Can" | ||||
| import {apiPath} from "auth/utils"; | |||||
| import {POST_LOGIN} from "utils/ApiPathConst"; | |||||
| // assets | // assets | ||||
| import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'; | import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'; | ||||
| import axios from "axios"; | import axios from "axios"; | ||||
| @@ -57,7 +60,7 @@ const AuthLogin = () => { | |||||
| }; | }; | ||||
| const tryLogin = () => { | const tryLogin = () => { | ||||
| axios.post('http://localhost:8090/api/login', | |||||
| axios.post(`${apiPath}${POST_LOGIN}`, | |||||
| { | { | ||||
| "username": userName, | "username": userName, | ||||
| "password": userPassword | "password": userPassword | ||||
| @@ -1,41 +1,36 @@ | |||||
| import { | |||||
| Grid, | |||||
| Button, | |||||
| TextField, | |||||
| } from '@mui/material'; | |||||
| import { Grid, Button, TextField } from '@mui/material'; | |||||
| import { useState } from 'react'; | import { useState } from 'react'; | ||||
| import axios from "axios"; | |||||
| import axios from 'axios'; | |||||
| const TestMailPage = ()=>{ | |||||
| const TestMailPage = () => { | |||||
| const [host, setHost] = useState('http://localhost:8090/api/test'); | |||||
| const [mail, setMail] = useState(''); | |||||
| const [host, setHost] = useState("http://localhost:8080/api/test"); | |||||
| const [mail, setMail] = useState(""); | |||||
| const hostChange = (event) => { | |||||
| setHost(event.target.value); | |||||
| }; | |||||
| const hostChange = (event)=>{ | |||||
| setHost(event.target.value); | |||||
| } | |||||
| const mailChange = (event) => { | |||||
| setMail(event.target.value); | |||||
| }; | |||||
| const mailChange = (event)=>{ | |||||
| setMail(event.target.value); | |||||
| } | |||||
| const doMailTest = ()=>{ | |||||
| axios.post(host, { | |||||
| email: mail | |||||
| }) | |||||
| .then((response) => { | |||||
| console.log(response.data); | |||||
| // Handle data | |||||
| }) | |||||
| .catch((error) => { | |||||
| console.log(error); | |||||
| }) | |||||
| } | |||||
| const doMailTest = () => { | |||||
| axios.post(host, { | |||||
| email: mail | |||||
| }) | |||||
| .then((response) => { | |||||
| console.log(response.data); | |||||
| // Handle data | |||||
| }) | |||||
| .catch((error) => { | |||||
| console.log(error); | |||||
| }) | |||||
| }; | |||||
| return ( | |||||
| <Grid | |||||
| return ( | |||||
| <Grid | |||||
| container | container | ||||
| alignItems="center" | |||||
| alignItems='center' | |||||
| sx={{ | sx={{ | ||||
| maxWidth: { xs: 1, lg: 1000 }, | maxWidth: { xs: 1, lg: 1000 }, | ||||
| margin: { xs: 2.5, md: 3 }, | margin: { xs: 2.5, md: 3 }, | ||||
| @@ -45,9 +40,9 @@ const TestMailPage = ()=>{ | |||||
| } | } | ||||
| }} | }} | ||||
| spacing={3}> | spacing={3}> | ||||
| <Grid item xs={12}><TextField id="hostField" label="Outlined" variant="filled" onChange={hostChange} value={host} fullWidth /></Grid> | |||||
| <Grid item xs={12}><TextField id="mailField" label="Outlined" variant="filled" onChange={mailChange} value={mail} fullWidth /></Grid> | |||||
| <Grid item xs={12}><Button variant="contained" onClick={doMailTest}>Test</Button></Grid> | |||||
| <Grid item xs={12}><TextField id='hostField' label='Outlined' variant='filled' onChange={hostChange} value={host} fullWidth /></Grid> | |||||
| <Grid item xs={12}><TextField id='mailField' label='Outlined' variant='filled' onChange={mailChange} value={mail} fullWidth /></Grid> | |||||
| <Grid item xs={12}><Button variant='contained' onClick={doMailTest}>Test</Button></Grid> | |||||
| </Grid> | </Grid> | ||||
| ); | ); | ||||
| }; | }; | ||||
| @@ -1,10 +1,19 @@ | |||||
| export const GET_GROUP_LIST_PATH = "/group" | |||||
| export const GET_GROUP_COMBO_PATH = "/group/combo" | |||||
| export const GET_GROUP_MEMBER_LIST_PATH = "/group/member" | |||||
| export const GET_GROUP_AUTH_LIST = "/group/auth/combo" | |||||
| export const GET_USER_PATH = "/user" | |||||
| export const GET_PUBLIC_USER_PATH = "/user/public" | |||||
| export const GET_AUTH_LIST = "/user/auth/combo" | |||||
| export const GET_USER_COMBO_LIST = "/user/combo" | |||||
| export const POST_PUBLIC_USER_REGISTER = "/user/register" | |||||
| // GET request | |||||
| //Group Config | |||||
| export const GET_GROUP_LIST_PATH = '/group'; | |||||
| export const GET_GROUP_COMBO_PATH = '/group/combo'; | |||||
| export const GET_GROUP_MEMBER_LIST_PATH = '/group/member'; | |||||
| export const GET_GROUP_AUTH_LIST = '/group/auth/combo'; | |||||
| export const GET_USER_PATH = '/user'; | |||||
| export const GET_PUBLIC_USER_PATH = '/user/public'; | |||||
| export const GET_AUTH_LIST = '/user/auth/combo'; | |||||
| export const GET_USER_COMBO_LIST = '/user/combo'; | |||||
| // POST request | |||||
| //Login | |||||
| export const POST_LOGIN = '/login'; | |||||
| //register | |||||
| export const POST_PUBLIC_USER_REGISTER = '/user/register'; | |||||