diff --git a/ui/src/LoginPage.tsx b/ui/src/LoginPage.tsx
index e044e012f..9cbd37ab8 100644
--- a/ui/src/LoginPage.tsx
+++ b/ui/src/LoginPage.tsx
@@ -1,29 +1,155 @@
+import { HtmlHTMLAttributes, ReactNode } from 'react';
import { useState } from 'react';
-import { useLogin, useNotify } from 'react-admin';
+import {
+ Form,
+ useLogin,
+ useNotify,
+ TextInput,
+ useSafeSetState,
+} from 'react-admin';
+import { styled } from '@mui/material/styles';
+import {
+ Button,
+ CardContent,
+ CircularProgress,
+ Avatar,
+ Card,
+ SxProps,
+} from '@mui/material';
+import LockIcon from '@mui/icons-material/Lock';
-const LoginPage = ({ theme }) => {
+const LoginPage = (props: LoginFormProps) => {
const [token, setToken] = useState('');
const login = useLogin();
const notify = useNotify();
+ const avatarIcon = ;
+ const { className } = props;
+ const [loading, setLoading] = useSafeSetState(false);
const handleSubmit = e => {
e.preventDefault();
- login({ token }).catch(() =>
- notify('Invalid token')
- );
+ setLoading(true);
+ login({ token }).catch(() => {
+ setLoading(false);
+ notify('Invalid token');
+ });
};
return (
-
+
+
+
+
+ setToken(e.target.value)}
+ />
+
+
+
+
+
+
);
};
export default LoginPage;
+export interface LoginProps extends HtmlHTMLAttributes {
+ avatarIcon?: ReactNode;
+ backgroundImage?: string;
+ children?: ReactNode;
+ className?: string;
+ sx?: SxProps;
+}
+
+const PREFIX = 'RaLogin';
+export const LoginClasses = {
+ card: `${PREFIX}-card`,
+ avatar: `${PREFIX}-avatar`,
+ icon: `${PREFIX}-icon`,
+};
+
+const Root = styled('div', {
+ name: PREFIX,
+ overridesResolver: (props, styles) => styles.root,
+})(({ theme }) => ({
+ display: 'flex',
+ flexDirection: 'column',
+ minHeight: '100vh',
+ height: '1px',
+ alignItems: 'center',
+ justifyContent: 'flex-start',
+ backgroundRepeat: 'no-repeat',
+ backgroundSize: 'cover',
+ backgroundImage:
+ 'radial-gradient(circle at 50% 14em, #313264 0%, #00023b 60%, #00023b 100%)',
+
+ [`& .${LoginClasses.card}`]: {
+ minWidth: 300,
+ marginTop: '6em',
+ },
+ [`& .${LoginClasses.avatar}`]: {
+ margin: '1em',
+ display: 'flex',
+ justifyContent: 'center',
+ },
+ [`& .${LoginClasses.icon}`]: {
+ backgroundColor: theme.palette.secondary[500],
+ },
+}));
+
+const PREFIXF = 'RaLoginForm';
+
+export const LoginFormClasses = {
+ content: `${PREFIXF}-content`,
+ button: `${PREFIXF}-button`,
+ icon: `${PREFIXF
+ }-icon`,
+};
+
+const StyledForm = styled(Form, {
+ name: PREFIXF,
+ overridesResolver: (props, styles) => styles.root,
+})(({ theme }) => ({
+ [`& .${LoginFormClasses.content}`]: {
+ width: 300,
+ },
+ [`& .${LoginFormClasses.button}`]: {
+ marginTop: theme.spacing(2),
+ },
+ [`& .${LoginFormClasses.icon}`]: {
+ margin: theme.spacing(0.3),
+ },
+}));
+
+export interface LoginFormProps {
+ redirectTo?: string;
+ className?: string;
+}