1- import  React ,  {  Dispatch ,  useContext ,  useEffect  }  from  'react' ; 
2- import  Router  from  './routes/Router' ; 
3- import  Layout  from  './components/Layout/Layout' ; 
4- import  {  connect  }  from  'react-redux' ; 
5- import  *  as  actions  from  './auth/authActions' ; 
6- import  {  PrivateRouteProps  }  from  './routes/PrivateRoute' ; 
7- import  {  Dialog ,  DialogActions ,  DialogContent ,  DialogTitle ,  Snackbar ,  ThemeProvider  }  from  '@material-ui/core' ; 
8- import  {  theme  }  from  './Theme' 
9- import  {  AlertContext  }  from  './contexts/AlertContext' ; 
10- import  Alert  from  '@material-ui/lab/Alert' ; 
11- import  {  AxiosError  }  from  './interfaces/axios/AxiosError' 
12- import  {  ThemeContext  }  from  './contexts/ThemeContext' ; 
13- import  {  useLocation  }  from  "react-router-dom" ; 
14- import  {  DialogContext  }  from  './contexts/DialogContext' ; 
1+ import  React ,  {  useContext ,  useEffect ,  useMemo ,  useState  }  from  "react" ; 
2+ import  { 
3+  BrowserRouter  as  Router , 
4+  Switch , 
5+  Route , 
6+  useLocation , 
7+  Redirect , 
8+  useHistory , 
9+ }  from  "react-router-dom" ; 
10+ import  axios  from  'axios' ; 
11+ import  {  ThemeProvider ,  CssBaseline ,  Snackbar ,  Dialog ,  DialogTitle ,  DialogContent ,  DialogActions  }  from  "@material-ui/core" ; 
1512
13+ import  {  useAppSelector  }  from  './redux/hooks' ; 
14+ import  {  Login  }  from  './components/Login/Login' ; 
15+ import  {  appArray  }  from  "./routes/Routes" ; 
16+ import  PrivateRoute  from  "./routes/PrivateRoute" ; 
17+ import  Layout  from  "./components/Layout/Layout" ; 
18+ import  Footer  from  "./components/Layout/Footer" ; 
19+ import  {  theme  }  from  "./Theme" ; 
20+ import  {  DialogContext  }  from  "./contexts/DialogContext" ; 
21+ import  {  Alert  }  from  "@material-ui/lab" ; 
22+ import  {  AlertContext  }  from  "./contexts/AlertContext" ; 
23+ import  PasswordUpdate  from  "./components/Login/PasswordUpdate" ; 
24+ import  PasswordReset  from  "./components/Login/PasswordReset" ; 
1625
17- type  Error  =  { 
18-  message : string 
19-  response : { 
20-  data : Record < string ,  string [ ] > 
21-  } 
22- } 
23- export  interface  AuthProps  { 
24-  logout : Function 
25-  setAuthenticatedIfRequired : Function 
26-  onAuth : Function 
27-  token : string 
28-  error : Error 
29- } 
30- 31- export  interface  AppProps  extends  AuthProps ,  PrivateRouteProps  {  } 
32- 33- function  App ( props : AppProps )  { 
34- 35-  const  {  alertType,  openAlert,  alertMessage,  handleAlertClose }  =  useContext ( AlertContext ) ; 
26+ export  function  App ( )  { 
27+  const  location  =  useLocation ( ) ; 
28+  const  {  authenticated }  =  useAppSelector ( state  =>  state . auth ) 
29+  const  {  darkMode }  =  useAppSelector ( state  =>  state . darkMode ) 
30+  const  history  =  useHistory ( ) 
3631 const  {  showDialog,  dialogTitle,  dialogBody,  dialogActions,  handleDialogClose }  =  useContext ( DialogContext ) ; 
37-  const  {  darkMode }  =  useContext ( ThemeContext ) ; 
38-  const  palletType  =  darkMode  ? "dark"  : "light" 
39-  const  location  =  useLocation ( ) . pathname 
32+  const  {  alertType,  openAlert,  alertMessage,  handleAlertClose }  =  useContext ( AlertContext ) ; 
4033
4134 useEffect ( ( )  =>  { 
42-  props . setAuthenticatedIfRequired ( ) ; 
43-  } ,  [ props ] ) ; 
35+  if  ( authenticated )  { 
36+  axios . get ( '/api/auth/loggedin/' ) 
37+  } 
38+  } ,  [ ] ) 
4439
45-  useEffect ( ( )  =>  { 
46-  handleAlertClose ( ) 
47-  } ,  [ location ] ) 
40+  const  publicRoutes  =  [ 
41+  {  path : "login" ,  component : Login ,  exact : true  } , 
42+  {  path : "password_reset" ,  component : PasswordReset ,  exact : true  } 
43+  ] 
4844
49-  return  ( 
50-  < div  className = "App" > 
51-  < ThemeProvider  theme = { theme ( palletType ) } > 
52-  < Layout  { ...props }  > 
53-  < Router  { ...props }  /> 
54-  </ Layout > 
55-  < Snackbar  id = "appAlertSnackbar"  open = { openAlert }  autoHideDuration = { 6000 }  onClose = { handleAlertClose } > 
56-  < Alert  variant = "filled"  onClose = { handleAlertClose }  severity = { alertType } > 
57-  { alertMessage } 
58-  </ Alert > 
59-  </ Snackbar > 
60-  < Dialog  maxWidth = "md"  fullWidth  open = { showDialog }  onClose = { handleDialogClose }  aria-labelledby = "alert-dialog-title" > 
61-  < DialogTitle  id = "alert-dialog-title" > { dialogTitle } </ DialogTitle > 
62-  < DialogContent > 
63-  { dialogBody } 
64-  </ DialogContent > 
65-  < DialogActions > 
66-  { dialogActions } 
67-  </ DialogActions > 
68-  </ Dialog > 
69-  </ ThemeProvider > 
70-  </ div > 
71-  ) ; 
72- } 
45+  const  atPublicRoute  =  publicRoutes . findIndex ( route  =>  location . pathname . includes ( route . path ) )  !==  - 1 
7346
74- interface MapStateToPropsInterface  { 
75-  auth :  { 
76-  token :  string , 
77-  error :  AxiosError 
78-  } 
79- } 
47+ useEffect ( ( ) =>  { 
48+  // when un-authenticated, redirect to login (only for non-public routes) 
49+  if ( ! authenticated && ! atPublicRoute ) { 
50+  history . push ( { pathname :  "/login" , state :  { from :  location } } ) 
51+  } 
52+ } , [ authenticated , location . pathname ] ) 
8053
81- //This means that one or more of the redux states in the store are available as props 
82- const  mapStateToProps  =  ( state : MapStateToPropsInterface )  =>  { 
83-  return  { 
84-  isAuthenticated : state . auth . token  !==  null  &&  typeof  state . auth . token  !==  'undefined' , 
85-  token : state . auth . token , 
86-  error : state . auth . error 
54+  const  generateAppRoutes  =  ( )  =>  { 
55+  return  appArray 
56+  . map ( ( app ,  index1 )  =>  { 
57+  let  result  =  app . routes ?. map ( ( route ,  index2 )  =>  { 
58+  const  key  =  `${ index1 } ${ index2 }  
59+  return  < PrivateRoute  key = { key }  exact = { route . exact }  path = { route . path }  component = { route . component }  /> ; 
60+  } ) 
61+  return  result 
62+  } ) 
8763 } 
88- } 
8964
90- //This means that one or more of the redux actions in the form of dispatch(action) combinations are available as props 
91- const  mapDispatchToProps  =  ( dispatch : Dispatch < any > )  =>  { 
92-  return  { 
93-  setAuthenticatedIfRequired : ( )  =>  dispatch ( actions . authCheckState ( ) ) , 
94-  logout : ( )  =>  dispatch ( actions . authLogout ( ) ) 
95-  } 
65+  const  privateRoutes  =  useMemo ( ( )  =>  generateAppRoutes ( ) ,  [ ] ) ; 
66+ 67+  return  ( 
68+  < ThemeProvider  theme = { theme ( darkMode  ? "dark"  : "light" ) } > 
69+  < CssBaseline  /> 
70+  < Snackbar  id = "appAlertSnackbar"  open = { openAlert }  autoHideDuration = { 6000 }  onClose = { handleAlertClose } > 
71+  < Alert  variant = "filled"  onClose = { handleAlertClose }  severity = { alertType } > 
72+  { alertMessage } 
73+  </ Alert > 
74+  </ Snackbar > 
75+  < Dialog  maxWidth = "md"  fullWidth  open = { showDialog }  onClose = { handleDialogClose }  aria-labelledby = "alert-dialog-title" > 
76+  < DialogTitle  id = "alert-dialog-title" > { dialogTitle } </ DialogTitle > 
77+  < DialogContent > 
78+  { dialogBody } 
79+  </ DialogContent > 
80+  < DialogActions > 
81+  { dialogActions } 
82+  </ DialogActions > 
83+  </ Dialog > 
84+  < Layout > 
85+  < div  className = { atPublicRoute  ? ""  : "content-wrap" } > 
86+  < div  className = { atPublicRoute  ? ""  : "container-fluid body main_container" } > 
87+  < Switch > 
88+  { publicRoutes . map ( ( route ,  index )  => 
89+  < Route  key = { index }  component = { route . component }  path = { "/"  +  route . path }  exact = { route . exact }  /> 
90+  ) } 
91+  { privateRoutes } 
92+  < PrivateRoute  component = { PasswordUpdate }  path = { "/change_password" } /> 
93+  < Redirect  from = "/"  to = { "/home" }  /> 
94+  </ Switch > 
95+  </ div > 
96+  </ div > 
97+  </ Layout > 
98+  < Footer  /> 
99+  </ ThemeProvider > 
100+  ) 
96101} 
97102
98- export  default  connect ( mapStateToProps ,  mapDispatchToProps ) ( App ) ; 
103+ export  function  MainPage ( )  { 
104+  return  ( 
105+  < Router > 
106+  < App  /> 
107+  </ Router > 
108+  ) 
109+ } 
0 commit comments