@campxdev/campx-web-utils 0.1.19 → 0.2.0
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/export.ts +4 -0
- package/package.json +2 -2
- package/src/App.tsx +3 -3
- package/src/Layout/AppLayout.tsx +1 -1
- package/src/Pages/main.tsx +6 -6
- package/src/context/ErrorBoundary/ErrorBoundary.tsx +23 -23
- package/src/context/ErrorBoundary/Login.tsx +38 -36
- package/src/context/Providers.tsx +17 -4
- package/src/hooks/export.ts +1 -1
- package/src/index.tsx +2 -2
- package/src/utils/breadcrumbs.ts +23 -0
- package/src/utils/export.ts +1 -0
- package/exports.ts +0 -3
package/export.ts
ADDED
package/package.json
CHANGED
package/src/App.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { useRoutes } from
|
|
1
|
+
import { useRoutes } from 'react-router-dom';
|
|
2
2
|
|
|
3
|
-
import { mainRoutes } from
|
|
4
|
-
import { Providers } from
|
|
3
|
+
import { mainRoutes } from './Pages/main';
|
|
4
|
+
import { Providers } from './context/export';
|
|
5
5
|
|
|
6
6
|
export default function App() {
|
|
7
7
|
return (
|
package/src/Layout/AppLayout.tsx
CHANGED
package/src/Pages/main.tsx
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { Navigate } from
|
|
2
|
-
import AppContent from
|
|
3
|
-
import AppLayout from
|
|
1
|
+
import { Navigate } from 'react-router-dom';
|
|
2
|
+
import AppContent from '../AppContent';
|
|
3
|
+
import AppLayout from '../Layout/AppLayout';
|
|
4
4
|
|
|
5
5
|
export const mainRoutes = [
|
|
6
6
|
{
|
|
7
|
-
path:
|
|
7
|
+
path: '/',
|
|
8
8
|
element: <AppLayout />,
|
|
9
9
|
children: [
|
|
10
10
|
{
|
|
11
11
|
index: true,
|
|
12
|
-
element: <Navigate to={
|
|
12
|
+
element: <Navigate to={'app-content'} />,
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
|
-
path:
|
|
15
|
+
path: 'app-content',
|
|
16
16
|
element: <AppContent />,
|
|
17
17
|
},
|
|
18
18
|
],
|
|
@@ -5,34 +5,34 @@ import {
|
|
|
5
5
|
NoInterneConnection,
|
|
6
6
|
PageNotFound,
|
|
7
7
|
UnAuthorized,
|
|
8
|
-
} from
|
|
9
|
-
import { Alert, Box, styled } from
|
|
10
|
-
import Cookies from
|
|
11
|
-
import { ReactNode, useState } from
|
|
12
|
-
import { ErrorBoundary as ReactErrorBoundary } from
|
|
13
|
-
import { QueryErrorResetBoundary } from
|
|
14
|
-
import { useLocation, useNavigate } from
|
|
15
|
-
import { Login } from
|
|
8
|
+
} from '@campxdev/react-blueprint';
|
|
9
|
+
import { Alert, Box, styled } from '@mui/material';
|
|
10
|
+
import Cookies from 'js-cookie';
|
|
11
|
+
import { ReactNode, useState } from 'react';
|
|
12
|
+
import { ErrorBoundary as ReactErrorBoundary } from 'react-error-boundary';
|
|
13
|
+
import { QueryErrorResetBoundary } from 'react-query';
|
|
14
|
+
import { useLocation, useNavigate } from 'react-router-dom';
|
|
15
|
+
import { Login } from './Login';
|
|
16
16
|
|
|
17
17
|
export type ErrorBoundaryProps = {
|
|
18
18
|
children: ReactNode;
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
const StyledAlert = styled(Alert)(({ theme }) => ({
|
|
22
|
-
height:
|
|
22
|
+
height: '60px',
|
|
23
23
|
border: `1px solid ${theme.palette.error.main}`,
|
|
24
|
-
display:
|
|
25
|
-
alignItems:
|
|
26
|
-
|
|
24
|
+
display: 'flex',
|
|
25
|
+
alignItems: 'center',
|
|
26
|
+
'& .MuiAlert-message': {
|
|
27
27
|
padding: 0,
|
|
28
28
|
},
|
|
29
|
-
|
|
29
|
+
'& .MuiTypography-root': {
|
|
30
30
|
margin: 0,
|
|
31
31
|
},
|
|
32
|
-
position:
|
|
33
|
-
|
|
34
|
-
color:
|
|
35
|
-
position:
|
|
32
|
+
position: 'relative',
|
|
33
|
+
'& .retryBtn': {
|
|
34
|
+
color: '#661B2A',
|
|
35
|
+
position: 'absolute',
|
|
36
36
|
right: 8,
|
|
37
37
|
top: 8,
|
|
38
38
|
},
|
|
@@ -68,12 +68,12 @@ const ErrorFallback = ({ error, resetErrorBoundary }: any) => {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
if (error?.code ===
|
|
71
|
+
if (error?.code === 'ERR_NETWORK') {
|
|
72
72
|
return <NoInterneConnection resetBoundary={resetErrorBoundary} />;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
return (
|
|
76
|
-
<Box sx={{ marginTop:
|
|
76
|
+
<Box sx={{ marginTop: '16px', padding: '20px' }}>
|
|
77
77
|
<StyledAlert severity="error">
|
|
78
78
|
{error?.response?.data?.message ?? error?.message}
|
|
79
79
|
<Button
|
|
@@ -94,14 +94,14 @@ const UnAuth = () => {
|
|
|
94
94
|
const navigate = useNavigate();
|
|
95
95
|
const [isModalOpen, setModalOpen] = useState(false);
|
|
96
96
|
|
|
97
|
-
const sessionCookie = Cookies.get(
|
|
97
|
+
const sessionCookie = Cookies.get('campx_session_key');
|
|
98
98
|
|
|
99
99
|
const handleLoginClick = () => {
|
|
100
|
-
if (window.location.hostname
|
|
100
|
+
if (window.location.hostname === 'localhost') {
|
|
101
101
|
setModalOpen(true);
|
|
102
102
|
} else {
|
|
103
103
|
if (!sessionCookie) {
|
|
104
|
-
navigate(
|
|
104
|
+
navigate('/auth/login');
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
};
|
|
@@ -112,7 +112,7 @@ const UnAuth = () => {
|
|
|
112
112
|
<>
|
|
113
113
|
<Button
|
|
114
114
|
sx={{
|
|
115
|
-
marginTop:
|
|
115
|
+
marginTop: '20px',
|
|
116
116
|
}}
|
|
117
117
|
variant="contained"
|
|
118
118
|
onClick={handleLoginClick}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { axios } from
|
|
2
|
-
import { Button, Icons, TextField } from
|
|
3
|
-
import { yupResolver } from
|
|
4
|
-
import { Box, Stack } from
|
|
5
|
-
import DeviceDetector from
|
|
6
|
-
import Cookies from
|
|
7
|
-
import { useEffect, useState } from
|
|
8
|
-
import { Controller, useForm } from
|
|
9
|
-
import { useMutation } from
|
|
1
|
+
import { axios } from '@campxdev/campx-web-utils';
|
|
2
|
+
import { Button, Icons, TextField } from '@campxdev/react-blueprint';
|
|
3
|
+
import { yupResolver } from '@hookform/resolvers/yup';
|
|
4
|
+
import { Box, Stack } from '@mui/material';
|
|
5
|
+
import DeviceDetector from 'device-detector-js';
|
|
6
|
+
import Cookies from 'js-cookie';
|
|
7
|
+
import { useEffect, useState } from 'react';
|
|
8
|
+
import { Controller, useForm } from 'react-hook-form';
|
|
9
|
+
import { useMutation } from 'react-query';
|
|
10
10
|
|
|
11
|
-
import * as Yup from
|
|
11
|
+
import * as Yup from 'yup';
|
|
12
12
|
|
|
13
13
|
type DeviceInformation = {
|
|
14
14
|
deviceType: string;
|
|
@@ -33,16 +33,16 @@ type LoginDetails = {
|
|
|
33
33
|
const performLogin = async (body: any) => {
|
|
34
34
|
if (!body.latitude || !body.longitude) {
|
|
35
35
|
const response = await fetch(
|
|
36
|
-
|
|
36
|
+
'https://www.googleapis.com/geolocation/v1/geolocate?key=AIzaSyB2YCpo1yi107RYj1LdZu2DCcpcO93reFY',
|
|
37
37
|
{
|
|
38
|
-
method:
|
|
38
|
+
method: 'POST',
|
|
39
39
|
headers: {
|
|
40
|
-
|
|
40
|
+
'Content-Type': 'application/json',
|
|
41
41
|
},
|
|
42
42
|
body: JSON.stringify({
|
|
43
|
-
considerIp:
|
|
43
|
+
considerIp: 'true',
|
|
44
44
|
}),
|
|
45
|
-
}
|
|
45
|
+
},
|
|
46
46
|
);
|
|
47
47
|
const data = await response.json();
|
|
48
48
|
body.latitude = data.location.lat;
|
|
@@ -52,20 +52,20 @@ const performLogin = async (body: any) => {
|
|
|
52
52
|
};
|
|
53
53
|
|
|
54
54
|
const validationSchema = Yup.object().shape({
|
|
55
|
-
username: Yup.string().required(
|
|
56
|
-
password: Yup.string().required(
|
|
55
|
+
username: Yup.string().required('Username is required'),
|
|
56
|
+
password: Yup.string().required('Password is required'),
|
|
57
57
|
});
|
|
58
58
|
|
|
59
59
|
export const Login = ({ close }: { close: () => void }) => {
|
|
60
60
|
const [deviceState, setDeviceState] = useState<DeviceState>({
|
|
61
61
|
deviceInformation: {
|
|
62
|
-
deviceType:
|
|
63
|
-
clientName:
|
|
64
|
-
os:
|
|
65
|
-
osVersion:
|
|
62
|
+
deviceType: 'browser',
|
|
63
|
+
clientName: 'unknown',
|
|
64
|
+
os: 'unknown',
|
|
65
|
+
osVersion: 'unknown',
|
|
66
66
|
latitude: null,
|
|
67
67
|
longitude: null,
|
|
68
|
-
tokenType:
|
|
68
|
+
tokenType: 'WEB',
|
|
69
69
|
},
|
|
70
70
|
isLocationAllowed: true,
|
|
71
71
|
});
|
|
@@ -82,9 +82,9 @@ export const Login = ({ close }: { close: () => void }) => {
|
|
|
82
82
|
}));
|
|
83
83
|
});
|
|
84
84
|
navigator.permissions
|
|
85
|
-
.query({ name:
|
|
85
|
+
.query({ name: 'geolocation' })
|
|
86
86
|
.then((permissionStatus) => {
|
|
87
|
-
if (permissionStatus.state ===
|
|
87
|
+
if (permissionStatus.state === 'denied') {
|
|
88
88
|
setDeviceState((s) => ({
|
|
89
89
|
...s,
|
|
90
90
|
isLocationAllowed: false,
|
|
@@ -109,17 +109,19 @@ export const Login = ({ close }: { close: () => void }) => {
|
|
|
109
109
|
handleSubmit,
|
|
110
110
|
control,
|
|
111
111
|
formState: { errors },
|
|
112
|
-
} = useForm<LoginDetails>({
|
|
112
|
+
} = useForm<LoginDetails>({
|
|
113
|
+
resolver: yupResolver<LoginDetails>(validationSchema),
|
|
114
|
+
});
|
|
113
115
|
|
|
114
116
|
const { mutate, isLoading } = useMutation(performLogin, {
|
|
115
117
|
onSuccess(data) {
|
|
116
118
|
if (data.loginSuccessful) {
|
|
117
|
-
Cookies.remove(
|
|
118
|
-
Cookies.remove(
|
|
119
|
-
Cookies.remove(
|
|
120
|
-
Cookies.set(
|
|
121
|
-
Cookies.set(
|
|
122
|
-
Cookies.set(
|
|
119
|
+
Cookies.remove('campx_session_key');
|
|
120
|
+
Cookies.remove('campx_tenant');
|
|
121
|
+
Cookies.remove('campx_institution');
|
|
122
|
+
Cookies.set('campx_session_key', data?.token);
|
|
123
|
+
Cookies.set('campx_tenant', data?.subDomain);
|
|
124
|
+
Cookies.set('campx_institution', data?.institutionCode);
|
|
123
125
|
close();
|
|
124
126
|
window.location.reload();
|
|
125
127
|
}
|
|
@@ -145,10 +147,10 @@ export const Login = ({ close }: { close: () => void }) => {
|
|
|
145
147
|
size="medium"
|
|
146
148
|
name="username"
|
|
147
149
|
sx={{
|
|
148
|
-
width:
|
|
150
|
+
width: '400px',
|
|
149
151
|
}}
|
|
150
152
|
placeholder="Enter Username or Email"
|
|
151
|
-
containerProps={{ my:
|
|
153
|
+
containerProps={{ my: '0' }}
|
|
152
154
|
onChange={field.onChange}
|
|
153
155
|
label="Username or Email"
|
|
154
156
|
error={!!errors.username}
|
|
@@ -166,11 +168,11 @@ export const Login = ({ close }: { close: () => void }) => {
|
|
|
166
168
|
size="medium"
|
|
167
169
|
name="password"
|
|
168
170
|
sx={{
|
|
169
|
-
width:
|
|
171
|
+
width: '400px',
|
|
170
172
|
}}
|
|
171
173
|
placeholder="Enter password"
|
|
172
174
|
onChange={field.onChange}
|
|
173
|
-
containerProps={{ my:
|
|
175
|
+
containerProps={{ my: '0' }}
|
|
174
176
|
label="Password"
|
|
175
177
|
type="password"
|
|
176
178
|
error={!!errors.password}
|
|
@@ -185,7 +187,7 @@ export const Login = ({ close }: { close: () => void }) => {
|
|
|
185
187
|
color="primary"
|
|
186
188
|
variant="contained"
|
|
187
189
|
sx={{
|
|
188
|
-
width:
|
|
190
|
+
width: '400px',
|
|
189
191
|
}}
|
|
190
192
|
onClick={handleSubmit(onSubmit)}
|
|
191
193
|
disabled={isLoading}
|
|
@@ -7,7 +7,15 @@ import { ConfirmDialogProvider } from './ConfirmDialogProvider';
|
|
|
7
7
|
import { ErrorBoundary } from './export';
|
|
8
8
|
import { SnackbarProvider } from './SnackbarProvider';
|
|
9
9
|
|
|
10
|
-
export const Providers = ({
|
|
10
|
+
export const Providers = ({
|
|
11
|
+
children,
|
|
12
|
+
basename,
|
|
13
|
+
theme = lightTheme,
|
|
14
|
+
}: {
|
|
15
|
+
children: ReactNode;
|
|
16
|
+
basename?: string;
|
|
17
|
+
theme?: any;
|
|
18
|
+
}) => {
|
|
11
19
|
const queryClient = new QueryClient({
|
|
12
20
|
defaultOptions: {
|
|
13
21
|
queries: {
|
|
@@ -18,15 +26,20 @@ export const Providers = ({ children, basename, theme = lightTheme }: { children
|
|
|
18
26
|
},
|
|
19
27
|
});
|
|
20
28
|
|
|
21
|
-
var tenantCode =
|
|
29
|
+
var tenantCode =
|
|
30
|
+
window.location.hostname === 'localhost'
|
|
31
|
+
? Cookies.get('campx_tenant')
|
|
32
|
+
: window.location.hostname.split('.')[0];
|
|
22
33
|
var institutionCode =
|
|
23
|
-
window.location.pathname.split('/')[1] !== ''
|
|
34
|
+
window.location.pathname.split('/')[1] !== ''
|
|
35
|
+
? window.location.pathname.split('/')[1]
|
|
36
|
+
: Cookies.get('campx_institution');
|
|
24
37
|
var baseName = tenantCode && institutionCode ? `/${institutionCode}` : '/';
|
|
25
38
|
useEffect(() => {
|
|
26
39
|
if (window.location.pathname === '/' && institutionCode && tenantCode) {
|
|
27
40
|
window.location.replace(window.location.origin + `/${institutionCode}`);
|
|
28
41
|
}
|
|
29
|
-
}, []);
|
|
42
|
+
}, [institutionCode, tenantCode]);
|
|
30
43
|
|
|
31
44
|
return (
|
|
32
45
|
<BrowserRouter basename={basename ?? baseName}>
|
package/src/hooks/export.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from
|
|
1
|
+
export * from './useConfirm';
|
package/src/index.tsx
CHANGED
|
@@ -5,12 +5,12 @@ import App from './App';
|
|
|
5
5
|
import reportWebVitals from './reportWebVitals';
|
|
6
6
|
|
|
7
7
|
const root = ReactDOM.createRoot(
|
|
8
|
-
document.getElementById('root') as HTMLElement
|
|
8
|
+
document.getElementById('root') as HTMLElement,
|
|
9
9
|
);
|
|
10
10
|
root.render(
|
|
11
11
|
<React.StrictMode>
|
|
12
12
|
<App />
|
|
13
|
-
</React.StrictMode
|
|
13
|
+
</React.StrictMode>,
|
|
14
14
|
);
|
|
15
15
|
|
|
16
16
|
// If you want to start measuring performance in your app, pass a function
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const getBreadcrumbsCharacter = () => {
|
|
2
|
+
const unicodeChar = String.fromCharCode(0x21e5);
|
|
3
|
+
const testElement = document.createElement('span');
|
|
4
|
+
testElement.innerHTML = unicodeChar;
|
|
5
|
+
document.body.appendChild(testElement);
|
|
6
|
+
const isRendered = testElement.offsetWidth > 0;
|
|
7
|
+
document.body.removeChild(testElement);
|
|
8
|
+
|
|
9
|
+
console.log(isRendered);
|
|
10
|
+
|
|
11
|
+
const fallbackChar = '~~';
|
|
12
|
+
const s = isRendered ? unicodeChar : fallbackChar;
|
|
13
|
+
|
|
14
|
+
return s;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
interface GetUrlSegment {
|
|
18
|
+
name: string;
|
|
19
|
+
id: string | number;
|
|
20
|
+
}
|
|
21
|
+
export const getUrlSegment = ({ name, id }: GetUrlSegment) => {
|
|
22
|
+
return `${name}${getBreadcrumbsCharacter()}${id}`;
|
|
23
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './breadcrumbs';
|
package/exports.ts
DELETED