@applica-software-guru/react-admin 1.0.59 → 1.0.61
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/README.md +1 -1
- package/dist/ApplicaAdmin.d.ts +28 -12
- package/dist/ApplicaAdmin.d.ts.map +1 -1
- package/dist/components/AuthBackground.d.ts +3 -0
- package/dist/components/AuthBackground.d.ts.map +1 -0
- package/dist/components/AuthCard.d.ts.map +1 -0
- package/dist/components/{ra-pages/LoginPage/AuthWrapper.d.ts → AuthWrapper.d.ts} +3 -1
- package/dist/components/AuthWrapper.d.ts.map +1 -0
- package/dist/components/Layout/Drawer/DrawerHeader/DrawerHeaderStyled.d.ts +1 -1
- package/dist/components/Layout/Header/HeaderContent/index.d.ts +3 -3
- package/dist/components/Layout/Header/index.d.ts +3 -3
- package/dist/components/Layout/index.d.ts +3 -3
- package/dist/components/ra-inputs/TextInput.d.ts +7 -6
- package/dist/components/ra-inputs/TextInput.d.ts.map +1 -1
- package/dist/components/ra-pages/LoginPage.d.ts +52 -0
- package/dist/components/ra-pages/LoginPage.d.ts.map +1 -0
- package/dist/components/ra-pages/RecoverPage.d.ts +12 -0
- package/dist/components/ra-pages/RecoverPage.d.ts.map +1 -0
- package/dist/components/ra-pages/RegisterPage.d.ts +11 -0
- package/dist/components/ra-pages/RegisterPage.d.ts.map +1 -0
- package/dist/components/ra-pages/index.d.ts +3 -1
- package/dist/components/ra-pages/index.d.ts.map +1 -1
- package/dist/components/ra-pages/types.d.ts +28 -0
- package/dist/components/ra-pages/types.d.ts.map +1 -0
- package/dist/hooks/useMenu.d.ts.map +1 -1
- package/dist/react-admin.cjs.js +52 -52
- package/dist/react-admin.cjs.js.map +1 -1
- package/dist/react-admin.es.js +7312 -7094
- package/dist/react-admin.es.js.map +1 -1
- package/dist/react-admin.umd.js +52 -52
- package/dist/react-admin.umd.js.map +1 -1
- package/package.json +4 -4
- package/src/ApplicaAdmin.tsx +45 -23
- package/src/assets/background.svg +58 -0
- package/src/components/AuthBackground.tsx +99 -0
- package/src/components/{ra-pages/LoginPage/AuthCard.jsx → AuthCard.jsx} +1 -1
- package/src/components/AuthWrapper.jsx +53 -0
- package/src/components/Layout/Header/HeaderContent/index.jsx +3 -3
- package/src/components/Layout/Header/index.jsx +3 -3
- package/src/components/Layout/index.jsx +3 -3
- package/src/components/ra-inputs/{TextInput.jsx → TextInput.tsx} +5 -3
- package/src/components/ra-pages/LoginPage.tsx +153 -0
- package/src/components/ra-pages/RecoverPage.tsx +75 -0
- package/src/components/ra-pages/RegisterPage.tsx +78 -0
- package/src/components/ra-pages/index.ts +3 -2
- package/src/components/ra-pages/types.ts +26 -0
- package/src/hooks/useMenu.jsx +6 -5
- package/src/playground/App.jsx +13 -7
- package/src/playground/config.jsx +1 -0
- package/src/playground/menu.jsx +0 -8
- package/dist/components/ra-pages/LoginPage/AuthCard.d.ts.map +0 -1
- package/dist/components/ra-pages/LoginPage/AuthLogin.d.ts +0 -6
- package/dist/components/ra-pages/LoginPage/AuthLogin.d.ts.map +0 -1
- package/dist/components/ra-pages/LoginPage/AuthWrapper.d.ts.map +0 -1
- package/dist/components/ra-pages/LoginPage/Login.d.ts +0 -34
- package/dist/components/ra-pages/LoginPage/Login.d.ts.map +0 -1
- package/dist/components/ra-pages/LoginPage/index.d.ts +0 -3
- package/dist/components/ra-pages/LoginPage/index.d.ts.map +0 -1
- package/src/components/ra-pages/LoginPage/AuthLogin.jsx +0 -79
- package/src/components/ra-pages/LoginPage/AuthWrapper.jsx +0 -46
- package/src/components/ra-pages/LoginPage/Login.tsx +0 -61
- package/src/components/ra-pages/LoginPage/index.jsx +0 -3
- /package/dist/components/{ra-pages/LoginPage/AuthCard.d.ts → AuthCard.d.ts} +0 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { Button, CircularProgress, Grid, Link, Stack, Typography } from '@mui/material';
|
|
2
|
+
import { Form, required, useCheckAuth, useLogin, useNotify, useSafeSetState, useTranslate } from 'ra-core';
|
|
3
|
+
import { Link as RouterLink, useNavigate } from 'react-router-dom';
|
|
4
|
+
|
|
5
|
+
import AuthBackground from '../AuthBackground';
|
|
6
|
+
import AuthWrapper from '../AuthWrapper';
|
|
7
|
+
import { BaseAuthProps } from './types';
|
|
8
|
+
import PropTypes from 'prop-types';
|
|
9
|
+
import { TextInput } from '../ra-inputs';
|
|
10
|
+
import { useEffect } from 'react';
|
|
11
|
+
|
|
12
|
+
export type LoginPageProps = BaseAuthProps & {
|
|
13
|
+
/**
|
|
14
|
+
* Indica se abilitare o meno la schermata di recupero password.
|
|
15
|
+
* Se abilitato è opportuno registrare una rotta a /recover con un componente
|
|
16
|
+
* che si occupi del recupero, puoi utilizzare direttamente il componente di Applica
|
|
17
|
+
*
|
|
18
|
+
* @see RecoverPage per maggiori informazioni.
|
|
19
|
+
* @example
|
|
20
|
+
* import { RecoverPage } from "@applica-software-guru/react-admin";
|
|
21
|
+
* <CustomRoutes noLayout>
|
|
22
|
+
* <Route path="/recover" component={RecoverPage} />
|
|
23
|
+
* </CustomRoutes>
|
|
24
|
+
*/
|
|
25
|
+
enablePasswordRecover?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Indica se abilitare o meno la schermata di registrazione.
|
|
28
|
+
* Se abilitato è opportuno registrare una rotta a /register con un componente
|
|
29
|
+
* che si occupi della registrazione, puoi utilizzare direttamente il componente di Applica
|
|
30
|
+
*
|
|
31
|
+
* @see RegisterPage per maggiori informazioni.
|
|
32
|
+
* @example
|
|
33
|
+
* import { RegisterPage } from "@applica-software-guru/react-admin";
|
|
34
|
+
* <CustomRoutes noLayout>
|
|
35
|
+
* <Route path="/register" component={RegisterPage} />
|
|
36
|
+
* </CustomRoutes>
|
|
37
|
+
*/
|
|
38
|
+
enableRegistration?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Indica la pagina a cui reindirizzare l'utente dopo il login.
|
|
41
|
+
* Se non specificata viene utilizzata la home page di react-admin.
|
|
42
|
+
*/
|
|
43
|
+
redirectTo: string;
|
|
44
|
+
};
|
|
45
|
+
const LoginPage = ({ version, name, enablePasswordRecover, enableRegistration, redirectTo, background }: LoginPageProps) => {
|
|
46
|
+
const [loading, setLoading] = useSafeSetState(false);
|
|
47
|
+
const login = useLogin();
|
|
48
|
+
const translate = useTranslate();
|
|
49
|
+
const notify = useNotify();
|
|
50
|
+
const checkAuth = useCheckAuth();
|
|
51
|
+
const navigate = useNavigate();
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
checkAuth({}, false)
|
|
54
|
+
.then(() => {
|
|
55
|
+
navigate('/');
|
|
56
|
+
})
|
|
57
|
+
.catch(() => {
|
|
58
|
+
// not authenticated, stay on the login page
|
|
59
|
+
});
|
|
60
|
+
}, [checkAuth, navigate]);
|
|
61
|
+
const handleSubmit = (values: any) => {
|
|
62
|
+
setLoading(true);
|
|
63
|
+
login(values, redirectTo)
|
|
64
|
+
.then(() => {
|
|
65
|
+
setLoading(false);
|
|
66
|
+
})
|
|
67
|
+
.catch((error) => {
|
|
68
|
+
setLoading(false);
|
|
69
|
+
notify(
|
|
70
|
+
typeof error === 'string' ? error : typeof error === 'undefined' || !error.message ? 'ra.auth.sign_in_error' : error.message,
|
|
71
|
+
{
|
|
72
|
+
type: 'error',
|
|
73
|
+
messageArgs: {
|
|
74
|
+
_: typeof error === 'string' ? error : error && error.message ? error.message : undefined
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
return (
|
|
81
|
+
<AuthWrapper name={name} version={version} background={background}>
|
|
82
|
+
<Grid container spacing={3}>
|
|
83
|
+
<Grid item xs={12}>
|
|
84
|
+
<Stack direction="row" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
|
|
85
|
+
<Typography variant="h3">Login</Typography>
|
|
86
|
+
{enableRegistration && (
|
|
87
|
+
<Typography component={RouterLink} to={'/register'} variant="body1" sx={{ textDecoration: 'none' }} color="primary">
|
|
88
|
+
{translate('ra.auth.register')}
|
|
89
|
+
</Typography>
|
|
90
|
+
)}
|
|
91
|
+
</Stack>
|
|
92
|
+
</Grid>
|
|
93
|
+
<Grid item xs={12}>
|
|
94
|
+
<Form onSubmit={handleSubmit}>
|
|
95
|
+
<Grid container>
|
|
96
|
+
<Grid item xs={12} sx={{ mb: 2 }}>
|
|
97
|
+
<TextInput
|
|
98
|
+
autoFocus
|
|
99
|
+
source="username"
|
|
100
|
+
label={translate('ra.auth.username')}
|
|
101
|
+
autoComplete="username"
|
|
102
|
+
validate={required()}
|
|
103
|
+
placeholder="user@company.name"
|
|
104
|
+
fullWidth
|
|
105
|
+
/>
|
|
106
|
+
</Grid>
|
|
107
|
+
<Grid item xs={12} sx={{ mb: 2 }}>
|
|
108
|
+
<TextInput
|
|
109
|
+
source="password"
|
|
110
|
+
label={translate('ra.auth.password')}
|
|
111
|
+
type="password"
|
|
112
|
+
autoComplete="current-password"
|
|
113
|
+
validate={required()}
|
|
114
|
+
placeholder={translate('ra.auth.password_placeholder')}
|
|
115
|
+
fullWidth
|
|
116
|
+
/>
|
|
117
|
+
</Grid>
|
|
118
|
+
</Grid>
|
|
119
|
+
{enablePasswordRecover && (
|
|
120
|
+
<Grid item xs={12} sx={{ mt: 1 }}>
|
|
121
|
+
<Stack direction="row" justifyContent="flex-end" alignItems="flex-end" spacing={2}>
|
|
122
|
+
<Link variant="h6" component={RouterLink} to={'/recover'} color="text.primary">
|
|
123
|
+
{translate('ra.auth.forgot_password')}
|
|
124
|
+
</Link>
|
|
125
|
+
</Stack>
|
|
126
|
+
</Grid>
|
|
127
|
+
)}
|
|
128
|
+
<Grid item xs={12} sx={{ mt: 1 }}>
|
|
129
|
+
<Button variant="contained" type="submit" color="primary" disabled={loading} fullWidth>
|
|
130
|
+
{loading ? <CircularProgress size={19} thickness={3} /> : translate('ra.auth.sign_in')}
|
|
131
|
+
</Button>
|
|
132
|
+
</Grid>
|
|
133
|
+
</Form>
|
|
134
|
+
</Grid>
|
|
135
|
+
</Grid>
|
|
136
|
+
</AuthWrapper>
|
|
137
|
+
);
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
LoginPage.propTypes = {
|
|
141
|
+
version: PropTypes.string.isRequired,
|
|
142
|
+
name: PropTypes.string.isRequired,
|
|
143
|
+
enablePasswordRecover: PropTypes.bool,
|
|
144
|
+
enableRegister: PropTypes.bool,
|
|
145
|
+
background: PropTypes.element
|
|
146
|
+
};
|
|
147
|
+
LoginPage.defaultProps = {
|
|
148
|
+
enablePasswordRecover: false,
|
|
149
|
+
enableRegister: false,
|
|
150
|
+
background: <AuthBackground />
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export default LoginPage;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import { Button, CircularProgress, Grid, Stack, Typography } from '@mui/material';
|
|
3
|
+
import React, { useState } from 'react';
|
|
4
|
+
import { email, required, useAuthProvider, useNotify, useRedirect, useTranslate } from 'ra-core';
|
|
5
|
+
|
|
6
|
+
import AuthWrapper from '../AuthWrapper';
|
|
7
|
+
import { BaseAuthProps } from './types';
|
|
8
|
+
import { Form } from 'react-admin';
|
|
9
|
+
import { Link } from 'react-router-dom';
|
|
10
|
+
import PropTypes from 'prop-types';
|
|
11
|
+
import { TextInput } from '../ra-inputs';
|
|
12
|
+
|
|
13
|
+
const RecoverPage = ({ name, version, background }: BaseAuthProps) => {
|
|
14
|
+
const [loading, setLoading] = useState(false);
|
|
15
|
+
const translate = useTranslate();
|
|
16
|
+
const redirect = useRedirect();
|
|
17
|
+
const notify = useNotify();
|
|
18
|
+
const authProvider = useAuthProvider();
|
|
19
|
+
|
|
20
|
+
const handleSubmit = ({ email }: any) => {
|
|
21
|
+
setLoading(true);
|
|
22
|
+
authProvider
|
|
23
|
+
.recover(email)
|
|
24
|
+
.then((response: any) => {
|
|
25
|
+
const message = `ra.auth.recover_${response.responseCode}`;
|
|
26
|
+
const type = response.responseCode === 'ok' ? 'info' : 'error';
|
|
27
|
+
// @ts-ignore
|
|
28
|
+
notify(message, { type });
|
|
29
|
+
redirect('/login');
|
|
30
|
+
})
|
|
31
|
+
.catch((error: any) => {
|
|
32
|
+
notify(error, { type: 'error' });
|
|
33
|
+
})
|
|
34
|
+
.finally(() => setLoading(false));
|
|
35
|
+
};
|
|
36
|
+
return (
|
|
37
|
+
<AuthWrapper name={name} version={version} background={background}>
|
|
38
|
+
<Grid container spacing={3}>
|
|
39
|
+
<Grid item xs={12}>
|
|
40
|
+
<Stack direction="row" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
|
|
41
|
+
<Typography variant="h3">{translate('ra.auth.recover.title')}</Typography>
|
|
42
|
+
<Typography component={Link} to={'/login'} variant="body1" sx={{ textDecoration: 'none' }} color="primary">
|
|
43
|
+
{translate('ra.auth.back_to_login')}
|
|
44
|
+
</Typography>
|
|
45
|
+
</Stack>
|
|
46
|
+
</Grid>
|
|
47
|
+
<Grid item xs={12}>
|
|
48
|
+
<Form onSubmit={handleSubmit}>
|
|
49
|
+
<Grid container>
|
|
50
|
+
<Grid item xs={12} sx={{ mb: 1 }}>
|
|
51
|
+
<TextInput source="email" validate={[required(), email()]} />
|
|
52
|
+
</Grid>
|
|
53
|
+
</Grid>
|
|
54
|
+
<Grid item xs={12} sx={{ mt: 1, mb: 1 }}>
|
|
55
|
+
<Typography variant="caption">{translate('ra.auth.recover.inbox_help')}</Typography>
|
|
56
|
+
</Grid>
|
|
57
|
+
<Grid item xs={12} sx={{ mt: 1 }}>
|
|
58
|
+
<Button variant="contained" type="submit" color="primary" disabled={loading} fullWidth>
|
|
59
|
+
{loading ? <CircularProgress size={19} thickness={3} /> : translate('ra.auth.recover')}
|
|
60
|
+
</Button>
|
|
61
|
+
</Grid>
|
|
62
|
+
</Form>
|
|
63
|
+
</Grid>
|
|
64
|
+
</Grid>
|
|
65
|
+
</AuthWrapper>
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
RecoverPage.propTypes = {
|
|
70
|
+
name: PropTypes.string.isRequired,
|
|
71
|
+
version: PropTypes.string.isRequired,
|
|
72
|
+
background: PropTypes.node
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export default RecoverPage;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import { Button, CircularProgress, Grid, Stack, Typography } from '@mui/material';
|
|
3
|
+
import { email, required, useAuthProvider, useNotify, useRedirect, useTranslate } from 'ra-core';
|
|
4
|
+
|
|
5
|
+
import AuthWrapper from '../AuthWrapper';
|
|
6
|
+
import { BaseAuthProps } from './types';
|
|
7
|
+
import { Form } from 'react-admin';
|
|
8
|
+
import { Link } from 'react-router-dom';
|
|
9
|
+
import PropTypes from 'prop-types';
|
|
10
|
+
import { TextInput } from '../ra-inputs';
|
|
11
|
+
import { useState } from 'react';
|
|
12
|
+
|
|
13
|
+
const RegisterPage = ({ name, version }: BaseAuthProps) => {
|
|
14
|
+
const [loading, setLoading] = useState(false);
|
|
15
|
+
const translate = useTranslate();
|
|
16
|
+
const redirect = useRedirect();
|
|
17
|
+
const notify = useNotify();
|
|
18
|
+
const authProvider = useAuthProvider();
|
|
19
|
+
|
|
20
|
+
const handleSubmit = (values: any) => {
|
|
21
|
+
setLoading(true);
|
|
22
|
+
authProvider
|
|
23
|
+
.register(values)
|
|
24
|
+
.then((response: any) => {
|
|
25
|
+
const message = `ra.auth.register_${response.responseCode}`;
|
|
26
|
+
const type = response.responseCode === 'ok' ? 'info' : 'error';
|
|
27
|
+
// @ts-ignore
|
|
28
|
+
notify(message, { type });
|
|
29
|
+
redirect('/login');
|
|
30
|
+
})
|
|
31
|
+
.catch((error: any) => {
|
|
32
|
+
console.log('error:', error);
|
|
33
|
+
notify(error, { type: 'error' });
|
|
34
|
+
})
|
|
35
|
+
.finally(() => setLoading(false));
|
|
36
|
+
};
|
|
37
|
+
return (
|
|
38
|
+
<AuthWrapper name={name} version={version}>
|
|
39
|
+
<Grid container spacing={3}>
|
|
40
|
+
<Grid item xs={12}>
|
|
41
|
+
<Stack direction="row" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
|
|
42
|
+
<Typography variant="h3">{translate('ra.auth.register.title')}</Typography>
|
|
43
|
+
<Typography component={Link} to={'/login'} variant="body1" sx={{ textDecoration: 'none' }} color="primary">
|
|
44
|
+
{translate('ra.auth.already_have_account')}
|
|
45
|
+
</Typography>
|
|
46
|
+
</Stack>
|
|
47
|
+
</Grid>
|
|
48
|
+
<Grid item xs={12}>
|
|
49
|
+
<Form onSubmit={handleSubmit}>
|
|
50
|
+
<Grid container>
|
|
51
|
+
<Grid item xs={12} sx={{ mb: 1 }}>
|
|
52
|
+
<TextInput source="name" label={translate('ra.register.name')} validate={required()} />
|
|
53
|
+
</Grid>
|
|
54
|
+
<Grid item xs={12} sx={{ mb: 1 }}>
|
|
55
|
+
<TextInput source="email" type="email" validate={[required(), email()]} />
|
|
56
|
+
</Grid>
|
|
57
|
+
<Grid item xs={12} sx={{ mb: 1 }}>
|
|
58
|
+
<TextInput source="password" type="password" validate={required()} />
|
|
59
|
+
</Grid>
|
|
60
|
+
</Grid>
|
|
61
|
+
<Grid item xs={12} sx={{ mt: 1 }}>
|
|
62
|
+
<Button variant="contained" type="submit" color="primary" disabled={loading} fullWidth>
|
|
63
|
+
{loading ? <CircularProgress size={19} thickness={3} /> : translate('ra.auth.create_account')}
|
|
64
|
+
</Button>
|
|
65
|
+
</Grid>
|
|
66
|
+
</Form>
|
|
67
|
+
</Grid>
|
|
68
|
+
</Grid>
|
|
69
|
+
</AuthWrapper>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
RegisterPage.propTypes = {
|
|
74
|
+
name: PropTypes.string.isRequired,
|
|
75
|
+
version: PropTypes.string.isRequired
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export default RegisterPage;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type BaseAuthProps = {
|
|
2
|
+
/**
|
|
3
|
+
* Versione dell'applicazione da mostrare.
|
|
4
|
+
*/
|
|
5
|
+
version: string;
|
|
6
|
+
/**
|
|
7
|
+
* Nome dell'applicazione da mostrare.
|
|
8
|
+
*/
|
|
9
|
+
name: string;
|
|
10
|
+
/**
|
|
11
|
+
* Immagine di sfondo della pagina.
|
|
12
|
+
* Se non specificata viene utilizzata l'immagine di default.
|
|
13
|
+
*
|
|
14
|
+
* @see AuthBackground per maggiori informazioni.
|
|
15
|
+
* @example
|
|
16
|
+
* // Esempio di Background personalizzato:
|
|
17
|
+
* const MyBackground = () => (
|
|
18
|
+
* <Box sx={{ position: 'absolute', filter: 'blur(20px)', bottom: 0, p: 4, pb: 8 }}>
|
|
19
|
+
* <svg width="100%" height="calc(100vh - 175px)" viewBox="0 0 117 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
20
|
+
* <path .. />
|
|
21
|
+
* </svg>
|
|
22
|
+
* </Box>
|
|
23
|
+
* )
|
|
24
|
+
*/
|
|
25
|
+
background: React.ReactNode | React.ElementType | any;
|
|
26
|
+
};
|
package/src/hooks/useMenu.jsx
CHANGED
|
@@ -176,15 +176,17 @@ const createNodes = ({ userGroups, resources, permissions, translate, roles }) =
|
|
|
176
176
|
const useMenu = () => {
|
|
177
177
|
const resources = useResourceDefinitions();
|
|
178
178
|
const { isLoading: loadingIdentity, data: identity } = useGetIdentity();
|
|
179
|
-
|
|
179
|
+
// Utilizziamo l'identità come discriminante per chiedere a react-query, eventualmente, dati aggiornati.
|
|
180
|
+
// Il rischio, senza questo passaggio, è di ricevere dati precedenti che non consentono di caricare correttamente la UX.
|
|
181
|
+
const isAuthenticated = identity && identity.id > 0;
|
|
182
|
+
|
|
183
|
+
const { isLoading: loadingPermissions, permissions } = usePermissions(isAuthenticated);
|
|
180
184
|
const { groups: userGroups } = useMenuConfig();
|
|
181
185
|
const translate = useTranslate();
|
|
182
|
-
|
|
183
186
|
const menu = useMemo(() => {
|
|
184
187
|
if (loadingIdentity || !identity || identity === null || identity?.id <= 0) {
|
|
185
188
|
return null;
|
|
186
189
|
}
|
|
187
|
-
|
|
188
190
|
const roles = (identity?.roles || []).map((role) => role.id);
|
|
189
191
|
const groups = createNodes({
|
|
190
192
|
resources,
|
|
@@ -193,9 +195,8 @@ const useMenu = () => {
|
|
|
193
195
|
userGroups,
|
|
194
196
|
roles
|
|
195
197
|
});
|
|
196
|
-
|
|
197
198
|
return groups;
|
|
198
|
-
}, [loadingIdentity, identity, resources, permissions, translate, userGroups]);
|
|
199
|
+
}, [loadingIdentity, loadingPermissions, identity, resources, permissions, translate, userGroups]);
|
|
199
200
|
|
|
200
201
|
const isLoading = useMemo(() => loadingIdentity, [loadingIdentity]);
|
|
201
202
|
|
package/src/playground/App.jsx
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import * as entities from './entities';
|
|
4
4
|
|
|
5
|
-
import { API_URL, FILE_FIELDS } from './config';
|
|
6
|
-
import { ApplicaAdmin, HttpError, Resource } from '@applica-software-guru/react-admin';
|
|
5
|
+
import { API_URL, APP_NAME, FILE_FIELDS } from './config';
|
|
6
|
+
import { ApplicaAdmin, HttpError, RecoverPage, RegisterPage, Resource } from '@applica-software-guru/react-admin';
|
|
7
7
|
import { createAttachmentsParser, createDataProvider } from '@applica-software-guru/crud-client';
|
|
8
8
|
|
|
9
9
|
import { CustomPage } from './components/pages';
|
|
@@ -32,17 +32,23 @@ const App = () => {
|
|
|
32
32
|
dataProvider={dataProvider}
|
|
33
33
|
defaultLocale="it"
|
|
34
34
|
menu={menu}
|
|
35
|
-
name=
|
|
35
|
+
name={APP_NAME}
|
|
36
36
|
version={build.version}
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
enableNotification
|
|
38
|
+
enableRegistration
|
|
39
|
+
enablePasswordRecover
|
|
39
40
|
>
|
|
41
|
+
<CustomRoutes>
|
|
42
|
+
<Route path="/custom-page" element={<CustomPage />} />
|
|
43
|
+
</CustomRoutes>
|
|
44
|
+
|
|
40
45
|
<Resource name="entities/notification" {...entities.notification} />
|
|
41
46
|
<Resource name="entities/user" {...entities.user} />
|
|
42
47
|
<Resource name="entities/i18n-message" {...entities.i18nMessage} />
|
|
43
48
|
<Resource name="entities/device" {...entities.device} />
|
|
44
|
-
<CustomRoutes>
|
|
45
|
-
<Route path="/
|
|
49
|
+
<CustomRoutes noLayout>
|
|
50
|
+
<Route path="/register" element={<RegisterPage name={APP_NAME} version={build.version} />} />
|
|
51
|
+
<Route path="/recover" element={<RecoverPage name={APP_NAME} version={build.version} />} />
|
|
46
52
|
</CustomRoutes>
|
|
47
53
|
</ApplicaAdmin>
|
|
48
54
|
);
|
|
@@ -4,6 +4,7 @@ if (appUrl.endsWith(':3000/') || appUrl.indexOf(':51') !== -1) {
|
|
|
4
4
|
appUrl = 'http://localhost:8080/';
|
|
5
5
|
environment = 'DEVELOPER';
|
|
6
6
|
}
|
|
7
|
+
export const APP_NAME = 'RApplica';
|
|
7
8
|
export const APP_URL = appUrl;
|
|
8
9
|
export const API_URL = `${APP_URL}api`;
|
|
9
10
|
export const ENVIRONMENT = environment;
|
package/src/playground/menu.jsx
CHANGED
|
@@ -13,14 +13,6 @@ const config = [
|
|
|
13
13
|
type: 'item',
|
|
14
14
|
url: '/entities/notification',
|
|
15
15
|
icon: NotificationOutlined
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
id: 'entities/bom',
|
|
19
|
-
title: 'ra.menu.item.entities/bom',
|
|
20
|
-
type: 'item',
|
|
21
|
-
url: '/entities/bom',
|
|
22
|
-
resource: true,
|
|
23
|
-
icon: TableOutlined
|
|
24
16
|
}
|
|
25
17
|
]
|
|
26
18
|
},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AuthCard.d.ts","sourceRoot":"","sources":["../../../../../src/components/ra-pages/LoginPage/AuthCard.jsx"],"names":[],"mappings":";AAKA;;;4CAqBC;;;;;;sBAxBqB,YAAY"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AuthLogin.d.ts","sourceRoot":"","sources":["../../../../../src/components/ra-pages/LoginPage/AuthLogin.jsx"],"names":[],"mappings":";AAMA;;;4CAsEC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AuthWrapper.d.ts","sourceRoot":"","sources":["../../../../../src/components/ra-pages/LoginPage/AuthWrapper.jsx"],"names":[],"mappings":";AAOA;;;;4CA8BC;;;;;;;;sBAhCqB,YAAY"}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import PropTypes from 'prop-types';
|
|
2
|
-
export type LoginProps = {
|
|
3
|
-
/**
|
|
4
|
-
* Versione dell'applicazione.
|
|
5
|
-
*/
|
|
6
|
-
version: string;
|
|
7
|
-
/**
|
|
8
|
-
* Nome dell'applicazione.
|
|
9
|
-
*/
|
|
10
|
-
name: string;
|
|
11
|
-
/**
|
|
12
|
-
* Indica se abilitare o meno la schermata di recupero password.
|
|
13
|
-
*/
|
|
14
|
-
enablePasswordForgot?: boolean;
|
|
15
|
-
/**
|
|
16
|
-
* Indica se abilitare o meno la schermata di registrazione.
|
|
17
|
-
*/
|
|
18
|
-
enableSignup?: boolean;
|
|
19
|
-
};
|
|
20
|
-
declare const Login: {
|
|
21
|
-
({ version, name, enablePasswordForgot, enableSignup }: LoginProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
-
propTypes: {
|
|
23
|
-
version: PropTypes.Validator<string>;
|
|
24
|
-
name: PropTypes.Validator<string>;
|
|
25
|
-
enablePasswordForgot: PropTypes.Requireable<boolean>;
|
|
26
|
-
enableSignup: PropTypes.Requireable<boolean>;
|
|
27
|
-
};
|
|
28
|
-
defaultProps: {
|
|
29
|
-
enablePasswordForgot: boolean;
|
|
30
|
-
enableSignup: boolean;
|
|
31
|
-
};
|
|
32
|
-
};
|
|
33
|
-
export default Login;
|
|
34
|
-
//# sourceMappingURL=Login.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Login.d.ts","sourceRoot":"","sources":["../../../../../src/components/ra-pages/LoginPage/Login.tsx"],"names":[],"mappings":"AAKA,OAAO,SAAS,MAAM,YAAY,CAAC;AAGnC,MAAM,MAAM,UAAU,GAAG;IACvB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AACF,QAAA,MAAM,KAAK;4DAA2D,UAAU;;;;;;;;;;;CAqB/E,CAAC;AAaF,eAAe,KAAK,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/ra-pages/LoginPage/index.jsx"],"names":[],"mappings":";kBAAkB,SAAS"}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { AnimateButton, TextInput } from '../../../components';
|
|
2
|
-
import { Button, CircularProgress, Grid, Link, Stack } from '@mui/material';
|
|
3
|
-
import { Form, required, useLogin, useNotify, useSafeSetState, useTranslate } from 'react-admin';
|
|
4
|
-
|
|
5
|
-
import { Link as RouterLink } from 'react-router-dom';
|
|
6
|
-
|
|
7
|
-
const AuthLogin = ({ enablePasswordForgot, ...props }) => {
|
|
8
|
-
const { redirectTo } = props;
|
|
9
|
-
const [loading, setLoading] = useSafeSetState(false);
|
|
10
|
-
const login = useLogin();
|
|
11
|
-
const translate = useTranslate();
|
|
12
|
-
const notify = useNotify();
|
|
13
|
-
|
|
14
|
-
const handleSubmit = (values) => {
|
|
15
|
-
setLoading(true);
|
|
16
|
-
login(values, redirectTo)
|
|
17
|
-
.then(() => {
|
|
18
|
-
setLoading(false);
|
|
19
|
-
})
|
|
20
|
-
.catch((error) => {
|
|
21
|
-
setLoading(false);
|
|
22
|
-
notify(
|
|
23
|
-
typeof error === 'string' ? error : typeof error === 'undefined' || !error.message ? 'ra.auth.sign_in_error' : error.message,
|
|
24
|
-
{
|
|
25
|
-
type: 'error',
|
|
26
|
-
messageArgs: {
|
|
27
|
-
_: typeof error === 'string' ? error : error && error.message ? error.message : undefined
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
);
|
|
31
|
-
});
|
|
32
|
-
};
|
|
33
|
-
return (
|
|
34
|
-
<Form onSubmit={handleSubmit}>
|
|
35
|
-
<Grid container>
|
|
36
|
-
<Grid item xs={12} sx={{ mb: 2 }}>
|
|
37
|
-
<TextInput
|
|
38
|
-
autoFocus
|
|
39
|
-
source="username"
|
|
40
|
-
label={translate('ra.auth.username')}
|
|
41
|
-
autoComplete="username"
|
|
42
|
-
validate={required()}
|
|
43
|
-
placeholder="user@company.name"
|
|
44
|
-
fullWidth
|
|
45
|
-
/>
|
|
46
|
-
</Grid>
|
|
47
|
-
<Grid item xs={12} sx={{ mb: 2 }}>
|
|
48
|
-
<TextInput
|
|
49
|
-
source="password"
|
|
50
|
-
label={translate('ra.auth.password')}
|
|
51
|
-
type="password"
|
|
52
|
-
autoComplete="current-password"
|
|
53
|
-
validate={required()}
|
|
54
|
-
placeholder={translate('ra.auth.password_placeholder')}
|
|
55
|
-
fullWidth
|
|
56
|
-
/>
|
|
57
|
-
</Grid>
|
|
58
|
-
</Grid>
|
|
59
|
-
{enablePasswordForgot && (
|
|
60
|
-
<Grid item xs={12} sx={{ mt: 1 }}>
|
|
61
|
-
<Stack direction="row" justifyContent="flex-end" alignItems="flex-end" spacing={2}>
|
|
62
|
-
<Link variant="h6" component={RouterLink} to={'/forgot-password'} color="text.primary">
|
|
63
|
-
{translate('ra.auth.forgot_password')}
|
|
64
|
-
</Link>
|
|
65
|
-
</Stack>
|
|
66
|
-
</Grid>
|
|
67
|
-
)}
|
|
68
|
-
<Grid item xs={12} sx={{ mt: 1 }}>
|
|
69
|
-
<AnimateButton>
|
|
70
|
-
<Button variant="contained" type="submit" color="primary" disabled={loading} fullWidth>
|
|
71
|
-
{loading ? <CircularProgress size={19} thickness={3} /> : translate('ra.auth.sign_in')}
|
|
72
|
-
</Button>
|
|
73
|
-
</AnimateButton>
|
|
74
|
-
</Grid>
|
|
75
|
-
</Form>
|
|
76
|
-
);
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
export default AuthLogin;
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { Box, Grid } from '@mui/material';
|
|
2
|
-
|
|
3
|
-
import AuthCard from './AuthCard';
|
|
4
|
-
import Footer from '../../Layout/Footer';
|
|
5
|
-
import MainIcon from '../../MainIcon';
|
|
6
|
-
import PropTypes from 'prop-types';
|
|
7
|
-
|
|
8
|
-
const AuthWrapper = ({ version, name, children }) => (
|
|
9
|
-
<Box sx={{ minHeight: '100vh' }}>
|
|
10
|
-
<Grid
|
|
11
|
-
container
|
|
12
|
-
direction="column"
|
|
13
|
-
justifyContent="flex-end"
|
|
14
|
-
sx={{
|
|
15
|
-
minHeight: '100vh'
|
|
16
|
-
}}
|
|
17
|
-
>
|
|
18
|
-
<Grid item xs={12} sx={{ ml: 3, mt: 3 }}>
|
|
19
|
-
<MainIcon title={name} />
|
|
20
|
-
</Grid>
|
|
21
|
-
<Grid item xs={12}>
|
|
22
|
-
<Grid
|
|
23
|
-
item
|
|
24
|
-
xs={12}
|
|
25
|
-
container
|
|
26
|
-
justifyContent="center"
|
|
27
|
-
alignItems="center"
|
|
28
|
-
sx={{ minHeight: { xs: 'calc(100vh - 210px)', sm: 'calc(100vh - 134px)', md: 'calc(100vh - 112px)' } }}
|
|
29
|
-
>
|
|
30
|
-
<Grid item>
|
|
31
|
-
<AuthCard>{children}</AuthCard>
|
|
32
|
-
</Grid>
|
|
33
|
-
</Grid>
|
|
34
|
-
<Footer name={name} version={version} />
|
|
35
|
-
</Grid>
|
|
36
|
-
</Grid>
|
|
37
|
-
</Box>
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
AuthWrapper.propTypes = {
|
|
41
|
-
children: PropTypes.node,
|
|
42
|
-
version: PropTypes.string,
|
|
43
|
-
name: PropTypes.string
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export default AuthWrapper;
|