@campxdev/shared 0.2.4 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@campxdev/shared",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
4
4
|
"main": "./exports.ts",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"start": "react-scripts start",
|
|
@@ -26,8 +26,11 @@
|
|
|
26
26
|
"@mui/icons-material": "^5.6.2",
|
|
27
27
|
"@mui/material": "^5.7.0",
|
|
28
28
|
"@mui/x-date-pickers": "^5.0.0-alpha.3",
|
|
29
|
+
"@types/js-cookie": "^3.0.2",
|
|
30
|
+
"@types/node": "^18.11.8",
|
|
29
31
|
"axios": "^0.27.2",
|
|
30
32
|
"date-fns": "^2.28.0",
|
|
33
|
+
"js-cookie": "^3.0.1",
|
|
31
34
|
"moment": "^2.29.4",
|
|
32
35
|
"pullstate": "^1.24.0",
|
|
33
36
|
"react": "^18.2.0",
|
|
@@ -1,150 +1,150 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import {Box, IconButton, Menu, styled, Typography} from '@mui/material'
|
|
2
|
+
import {AssetsStore} from '../../../shared-state/AssetsStore'
|
|
3
3
|
import CogWheelMenu from './CogWheelMenu'
|
|
4
4
|
import FreshDeskHelpButton from './FreshDeskHelpButton'
|
|
5
|
-
import {
|
|
5
|
+
import {StyledHeader, StyledImageWrapper} from './styles'
|
|
6
6
|
import UserBox from './UserBox'
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
7
|
+
import {Link} from 'react-router-dom'
|
|
8
|
+
import {useState} from 'react'
|
|
9
|
+
import {applications} from './applications'
|
|
10
|
+
import {AppsIcon} from './icons'
|
|
11
11
|
import Notification from './Notification'
|
|
12
12
|
|
|
13
|
-
export default function AppHeader({
|
|
14
|
-
|
|
13
|
+
export default function AppHeader({title}: {title?: string}) {
|
|
14
|
+
const assetState = AssetsStore.useState((s) => s)
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
return (
|
|
17
|
+
<StyledHeader>
|
|
18
|
+
<Box sx={{display: 'flex', alignItems: 'center', gap: '20px'}}>
|
|
19
|
+
<AppsMenu />
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
21
|
+
<Link to={'/'}>
|
|
22
|
+
{title ? (
|
|
23
|
+
<Typography variant='h1'>{title}</Typography>
|
|
24
|
+
) : (
|
|
25
|
+
<StyledImageWrapper>
|
|
26
|
+
<img src={assetState.logo} />
|
|
27
|
+
</StyledImageWrapper>
|
|
28
|
+
)}
|
|
29
|
+
</Link>
|
|
30
|
+
</Box>
|
|
31
|
+
<Box className='actions'>
|
|
32
|
+
<FreshDeskHelpButton />
|
|
33
|
+
<Notification />
|
|
34
|
+
<CogWheelMenu />
|
|
35
|
+
<UserBox />
|
|
36
|
+
</Box>
|
|
37
|
+
</StyledHeader>
|
|
38
|
+
)
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
const AppsMenu = () => {
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
const [anchorEl, setAnchorEl] = useState<any>(null)
|
|
43
|
+
const open = Boolean(anchorEl)
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
const handleClick = (event) => {
|
|
46
|
+
setAnchorEl(event.currentTarget)
|
|
47
|
+
}
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
const handleClose = () => {
|
|
50
|
+
setAnchorEl(null)
|
|
51
|
+
}
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
return (
|
|
54
|
+
<Box sx={{marginRight: '10px'}}>
|
|
55
|
+
<StyledIconButton onClick={handleClick}>
|
|
56
|
+
<AppsIcon />
|
|
57
|
+
</StyledIconButton>
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
59
|
+
<Menu
|
|
60
|
+
elevation={2}
|
|
61
|
+
id='basic-menu'
|
|
62
|
+
anchorEl={anchorEl}
|
|
63
|
+
open={open}
|
|
64
|
+
onClose={handleClose}
|
|
65
|
+
MenuListProps={{
|
|
66
|
+
sx: {
|
|
67
|
+
padding: 0,
|
|
68
|
+
margin: 0,
|
|
69
|
+
},
|
|
70
|
+
}}
|
|
71
|
+
anchorOrigin={{
|
|
72
|
+
vertical: 'bottom',
|
|
73
|
+
horizontal: 'left',
|
|
74
|
+
}}
|
|
75
|
+
transformOrigin={{
|
|
76
|
+
vertical: 'top',
|
|
77
|
+
horizontal: 'left',
|
|
78
|
+
}}
|
|
79
|
+
sx={{
|
|
80
|
+
'& .MuiPaper-root': {
|
|
81
|
+
left: '0px',
|
|
82
|
+
},
|
|
83
|
+
}}
|
|
84
|
+
>
|
|
85
|
+
<Box sx={{padding: '1rem 1.5rem'}}>
|
|
86
|
+
<Typography variant='h6'>Switch to</Typography>
|
|
87
|
+
</Box>
|
|
88
|
+
<Box>
|
|
89
|
+
{applications.map((item, index) => (
|
|
90
|
+
<StyledMenuItemContainer
|
|
91
|
+
key={index}
|
|
92
|
+
onClick={() => {
|
|
93
|
+
handleClose()
|
|
94
|
+
}}
|
|
95
|
+
>
|
|
96
|
+
<StyledMenuItem data={item} />
|
|
97
|
+
</StyledMenuItemContainer>
|
|
98
|
+
))}
|
|
99
|
+
</Box>
|
|
100
|
+
</Menu>
|
|
101
|
+
</Box>
|
|
102
|
+
)
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
const StyledMenuItem = ({
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
105
|
+
const StyledMenuItem = ({data}) => {
|
|
106
|
+
return (
|
|
107
|
+
<StyledMenuitem>
|
|
108
|
+
<Box>{data.icon}</Box>
|
|
109
|
+
<Box>
|
|
110
|
+
<Typography variant='h1'>{data?.title}</Typography>
|
|
111
|
+
<StyledDescription>{data?.description}</StyledDescription>
|
|
112
|
+
</Box>
|
|
113
|
+
</StyledMenuitem>
|
|
114
|
+
)
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
const StyledIconButton = styled(IconButton)({
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
118
|
+
padding: '20px',
|
|
119
|
+
backgroundColor: 'black',
|
|
120
|
+
display: 'flex',
|
|
121
|
+
alignItems: 'center',
|
|
122
|
+
justifyContent: 'center',
|
|
123
|
+
borderRadius: '0px',
|
|
124
124
|
})
|
|
125
125
|
|
|
126
|
-
const StyledDescription = styled(Typography)(({
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
126
|
+
const StyledDescription = styled(Typography)(({theme}) => ({
|
|
127
|
+
fontSize: '15px',
|
|
128
|
+
fontWeight: 500,
|
|
129
|
+
color: theme?.palette?.secondary?.main,
|
|
130
130
|
}))
|
|
131
131
|
|
|
132
132
|
const StyledMenuitem = styled(Box)({
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
133
|
+
height: '72px',
|
|
134
|
+
width: '400px',
|
|
135
|
+
padding: '40px 20px',
|
|
136
|
+
'&:hover': {
|
|
137
|
+
background: 'rgba(0, 0, 0, 0.03)',
|
|
138
|
+
},
|
|
139
|
+
display: 'flex',
|
|
140
|
+
alignItems: 'center',
|
|
141
|
+
gap: '10px',
|
|
142
142
|
})
|
|
143
143
|
|
|
144
|
-
const StyledMenuItemContainer = styled(Box)(({
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
144
|
+
const StyledMenuItemContainer = styled(Box)(({theme}) => ({
|
|
145
|
+
cursor: 'pointer',
|
|
146
|
+
borderBottom: `1px solid ${theme?.palette?.secondary?.lighter}`,
|
|
147
|
+
'&:last-of-type': {
|
|
148
|
+
border: 'none',
|
|
149
|
+
},
|
|
150
150
|
}))
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import {BoxProps, styled, Box, LinearProgress} from '@mui/material'
|
|
2
|
+
import {globalStore} from '../../shared-state/GlobalStore'
|
|
3
3
|
|
|
4
4
|
export default function LinearIndeterminate() {
|
|
5
|
-
|
|
5
|
+
const loading = globalStore.useState((s) => s).loading
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
if (!loading) return null
|
|
8
|
+
return <StyledLinearProgress />
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export const StyledLinearProgress = styled((props: BoxProps) => (
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
))(({
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
12
|
+
<Box {...props}>
|
|
13
|
+
<LinearProgress
|
|
14
|
+
color={'inherit'}
|
|
15
|
+
sx={{
|
|
16
|
+
height: '3px',
|
|
17
|
+
}}
|
|
18
|
+
/>
|
|
19
|
+
</Box>
|
|
20
|
+
))(({theme}) => ({
|
|
21
|
+
width: '100%',
|
|
22
|
+
position: 'fixed',
|
|
23
|
+
top: '64px',
|
|
24
|
+
left: 0,
|
|
25
|
+
zIndex: 400,
|
|
26
|
+
color: theme.palette.common.yellow,
|
|
27
27
|
}))
|
package/src/config/axios.ts
CHANGED
|
@@ -1,138 +1,137 @@
|
|
|
1
1
|
import Axios from 'axios'
|
|
2
2
|
import _ from 'lodash'
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import {toast} from 'react-toastify'
|
|
4
|
+
import {globalStore} from '../shared-state/GlobalStore'
|
|
5
5
|
import Cookies from 'js-cookie'
|
|
6
6
|
|
|
7
7
|
const isDevelopment = process.env.NODE_ENV === 'development'
|
|
8
8
|
const sessionKey = Cookies.get('campx_session_key')
|
|
9
9
|
|
|
10
10
|
const formatParams = (params) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
return Object.fromEntries(
|
|
12
|
+
Object.entries(params ?? {})?.map((i) => [
|
|
13
|
+
i[0],
|
|
14
|
+
i[1] === '__empty__' ? '' : i[1],
|
|
15
|
+
])
|
|
16
|
+
)
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
let axios = Axios.create({
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
baseURL: process.env.REACT_APP_API_HOST,
|
|
21
|
+
withCredentials: true,
|
|
22
|
+
...(isDevelopment && {
|
|
23
|
+
headers: {
|
|
24
|
+
campx_session_key: sessionKey,
|
|
25
|
+
},
|
|
26
|
+
}),
|
|
27
27
|
})
|
|
28
28
|
|
|
29
29
|
axios.interceptors.request.use(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
30
|
+
function (config) {
|
|
31
|
+
const params = formatParams(config?.params)
|
|
32
|
+
globalStore.update((s) => {
|
|
33
|
+
s.loading = true
|
|
34
|
+
s.error.message = ''
|
|
35
|
+
s.error.statusCode = null
|
|
36
|
+
s.error.description = ''
|
|
37
|
+
})
|
|
38
|
+
return {...config, params}
|
|
39
|
+
},
|
|
40
|
+
function (error) {
|
|
41
|
+
globalStore.update((s) => {
|
|
42
|
+
s.loading = true
|
|
43
|
+
})
|
|
44
|
+
return Promise.reject(error)
|
|
45
|
+
}
|
|
46
46
|
)
|
|
47
47
|
|
|
48
48
|
axios.interceptors.response.use(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
49
|
+
function (response) {
|
|
50
|
+
globalStore.update((s) => {
|
|
51
|
+
s.loading = false
|
|
52
|
+
})
|
|
53
|
+
return response
|
|
54
|
+
},
|
|
55
|
+
function (err) {
|
|
56
|
+
globalStore.update((s) => {
|
|
57
|
+
s.loading = false
|
|
58
|
+
})
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
60
|
+
if (err.message == 'Network Error') {
|
|
61
|
+
globalStore.update((s) => {
|
|
62
|
+
s.error = {
|
|
63
|
+
message: err.message,
|
|
64
|
+
statusCode: 999,
|
|
65
|
+
description: 'Please check your network connection',
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
} else {
|
|
69
|
+
const method = err.response.config.method
|
|
70
|
+
if (method === 'get' || method === 'GET') {
|
|
71
|
+
setError(err.response.status, err.response.data.message)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
return Promise.reject(err)
|
|
76
|
+
}
|
|
77
77
|
)
|
|
78
78
|
|
|
79
|
-
|
|
80
79
|
export default axios
|
|
81
80
|
|
|
82
81
|
export const axiosErrorToast = (error: any, fallback?: string) => {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
const fallbackMessage = fallback ?? 'Something went wrong.'
|
|
83
|
+
const errorMessage =
|
|
84
|
+
typeof error?.response?.data?.message !== 'string'
|
|
85
|
+
? error?.response?.data?.message?.join('\n') ?? fallbackMessage
|
|
86
|
+
: error?.response?.data?.message
|
|
88
87
|
|
|
89
|
-
|
|
88
|
+
return toast.error(errorMessage)
|
|
90
89
|
}
|
|
91
90
|
|
|
92
91
|
const setError = (statusCode: number, message: string) => {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
92
|
+
switch (statusCode) {
|
|
93
|
+
case 401:
|
|
94
|
+
localStorage.removeItem('token')
|
|
95
|
+
globalStore.update((s) => {
|
|
96
|
+
s.error.message = message ?? 'Session Expired!'
|
|
97
|
+
s.error.statusCode = statusCode
|
|
98
|
+
s.error.description =
|
|
99
|
+
'Your session has been expired, Please login to continue'
|
|
100
|
+
})
|
|
101
|
+
break
|
|
102
|
+
case 404:
|
|
103
|
+
// globalStore.update((s) => {
|
|
104
|
+
// s.error.message = message ?? 'Not Found!'
|
|
105
|
+
// s.error.statusCode = statusCode
|
|
106
|
+
// s.error.description =
|
|
107
|
+
// 'The resource you are trying to access is not found.'
|
|
108
|
+
// })
|
|
109
|
+
toast.error('The resource you are trying to access is not found.')
|
|
111
110
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
111
|
+
break
|
|
112
|
+
case 403:
|
|
113
|
+
globalStore.update((s) => {
|
|
114
|
+
s.error.message = message ?? 'Forbidden!'
|
|
115
|
+
s.error.statusCode = statusCode
|
|
116
|
+
s.error.description =
|
|
117
|
+
'The resource you are trying to access is forbidden.'
|
|
118
|
+
})
|
|
119
|
+
break
|
|
121
120
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
121
|
+
case 400:
|
|
122
|
+
case 422:
|
|
123
|
+
globalStore.update((s) => {
|
|
124
|
+
s.error.message = ''
|
|
125
|
+
s.error.description = ''
|
|
126
|
+
s.error.statusCode = null
|
|
127
|
+
})
|
|
128
|
+
break
|
|
130
129
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
130
|
+
default:
|
|
131
|
+
globalStore.update((s) => {
|
|
132
|
+
s.error.message = 'Unknown Network Error!'
|
|
133
|
+
s.error.statusCode = 999
|
|
134
|
+
s.error.description = 'Unknown network error occurred!'
|
|
135
|
+
})
|
|
136
|
+
}
|
|
138
137
|
}
|
|
@@ -1,58 +1,58 @@
|
|
|
1
1
|
import PermissionDeniedPage from './PermissionDeniedPage'
|
|
2
|
-
import {
|
|
3
|
-
import React, {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
2
|
+
import {PermissionsStore} from './PermissionsStore'
|
|
3
|
+
import React, {ReactNode, useEffect} from 'react'
|
|
4
|
+
import {globalStore} from '../shared-state/GlobalStore'
|
|
5
|
+
import {Box, Typography} from '@mui/material'
|
|
6
|
+
import {useHistory} from '../hooks/useRouter'
|
|
7
7
|
|
|
8
8
|
const accessIfNoKey = process.env.NODE_ENV === 'development' ? true : false
|
|
9
9
|
|
|
10
10
|
export default function PageWithPermission({
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
permissionKey,
|
|
12
|
+
component: Component,
|
|
13
|
+
children,
|
|
14
|
+
...props
|
|
15
15
|
}: {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
permissionKey: string
|
|
17
|
+
component?: any
|
|
18
|
+
children?: any
|
|
19
19
|
}) {
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
const history = useHistory()
|
|
21
|
+
const errorState = globalStore.useState((s) => s.error)
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
const permissions = PermissionsStore.useState((s) => s).permissions
|
|
24
|
+
const hasAccess = permissionKey ? permissions[permissionKey] : accessIfNoKey
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
globalStore.update((s) => {
|
|
28
|
+
s.error = {
|
|
29
|
+
message: '',
|
|
30
|
+
statusCode: null,
|
|
31
|
+
description: '',
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
}, [history])
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
if (errorState.statusCode) return <ErrorPage />
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
// if (hasAccess) return Component
|
|
39
|
+
if (hasAccess) return children
|
|
40
|
+
return <PermissionDeniedPage />
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
const ErrorPage = () => {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
44
|
+
const globalState = globalStore.useState((s) => s).error
|
|
45
|
+
return (
|
|
46
|
+
<Box
|
|
47
|
+
sx={{
|
|
48
|
+
display: 'flex',
|
|
49
|
+
alignItems: 'center',
|
|
50
|
+
justifyContent: 'center',
|
|
51
|
+
}}
|
|
52
|
+
>
|
|
53
|
+
<Typography variant='h1' marginTop={'100px'}>
|
|
54
|
+
{globalState.description}
|
|
55
|
+
</Typography>
|
|
56
|
+
</Box>
|
|
57
|
+
)
|
|
58
58
|
}
|