build(deps): update mui monorepo to v5.8.4 (major) (#3215)
parent
0a9dd4727d
commit
841e495dca
|
@ -17,13 +17,16 @@
|
|||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/cache": "11.9.3",
|
||||
"@emotion/react": "11.9.3",
|
||||
"@emotion/styled": "11.9.3",
|
||||
"@fortawesome/fontawesome-svg-core": "6.1.1",
|
||||
"@fortawesome/free-regular-svg-icons": "6.1.1",
|
||||
"@fortawesome/free-solid-svg-icons": "6.1.1",
|
||||
"@fortawesome/react-fontawesome": "0.1.18",
|
||||
"@material-ui/core": "4.12.4",
|
||||
"@material-ui/icons": "4.11.3",
|
||||
"@material-ui/styles": "4.11.5",
|
||||
"@mui/icons-material": "5.8.4",
|
||||
"@mui/material": "5.8.4",
|
||||
"@mui/styles": "5.8.4",
|
||||
"axios": "0.27.2",
|
||||
"classnames": "2.3.1",
|
||||
"i18next": "21.8.10",
|
||||
|
@ -151,7 +154,7 @@
|
|||
"@typescript-eslint/eslint-plugin": "5.29.0",
|
||||
"@typescript-eslint/parser": "5.29.0",
|
||||
"@vitejs/plugin-react": "1.3.2",
|
||||
"esbuild": "0.14.46",
|
||||
"esbuild": "0.14.17",
|
||||
"esbuild-jest": "0.5.0",
|
||||
"eslint": "8.18.0",
|
||||
"eslint-config-prettier": "8.5.0",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,9 @@
|
|||
import React, { useState, useEffect, Suspense } from "react";
|
||||
|
||||
import createCache from "@emotion/cache";
|
||||
import { CacheProvider } from "@emotion/react";
|
||||
import { config as faConfig } from "@fortawesome/fontawesome-svg-core";
|
||||
import { CssBaseline, ThemeProvider } from "@material-ui/core";
|
||||
import { CssBaseline, ThemeProvider } from "@mui/material";
|
||||
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
|
||||
|
||||
import NotificationBar from "@components/NotificationBar";
|
||||
|
@ -51,9 +53,20 @@ function Theme() {
|
|||
}
|
||||
}
|
||||
|
||||
const App: React.FC = () => {
|
||||
export interface Props {
|
||||
nonce?: string;
|
||||
}
|
||||
|
||||
const App: React.FC<Props> = (props: Props) => {
|
||||
const [notification, setNotification] = useState(null as Notification | null);
|
||||
const [theme, setTheme] = useState(Theme());
|
||||
|
||||
const cache = createCache({
|
||||
key: "authelia",
|
||||
nonce: props.nonce,
|
||||
prepend: true,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (getTheme() === "auto") {
|
||||
const query = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
|
@ -66,35 +79,37 @@ const App: React.FC = () => {
|
|||
}
|
||||
}, []);
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
<Suspense fallback={<BaseLoadingPage message={"Loading"} />}>
|
||||
<CssBaseline />
|
||||
<NotificationsContext.Provider value={{ notification, setNotification }}>
|
||||
<Router basename={getBasePath()}>
|
||||
<NotificationBar onClose={() => setNotification(null)} />
|
||||
<Routes>
|
||||
<Route path={ResetPasswordStep1Route} element={<ResetPasswordStep1 />} />
|
||||
<Route path={ResetPasswordStep2Route} element={<ResetPasswordStep2 />} />
|
||||
<Route path={RegisterWebauthnRoute} element={<RegisterWebauthn />} />
|
||||
<Route path={RegisterOneTimePasswordRoute} element={<RegisterOneTimePassword />} />
|
||||
<Route path={LogoutRoute} element={<SignOut />} />
|
||||
<Route path={ConsentRoute} element={<ConsentView />} />
|
||||
<Route
|
||||
path={`${IndexRoute}*`}
|
||||
element={
|
||||
<LoginPortal
|
||||
duoSelfEnrollment={getDuoSelfEnrollment()}
|
||||
rememberMe={getRememberMe()}
|
||||
resetPassword={getResetPassword()}
|
||||
resetPasswordCustomURL={getResetPasswordCustomURL()}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
</Router>
|
||||
</NotificationsContext.Provider>
|
||||
</Suspense>
|
||||
</ThemeProvider>
|
||||
<CacheProvider value={cache}>
|
||||
<ThemeProvider theme={theme}>
|
||||
<Suspense fallback={<BaseLoadingPage message={"Loading"} />}>
|
||||
<CssBaseline />
|
||||
<NotificationsContext.Provider value={{ notification, setNotification }}>
|
||||
<Router basename={getBasePath()}>
|
||||
<NotificationBar onClose={() => setNotification(null)} />
|
||||
<Routes>
|
||||
<Route path={ResetPasswordStep1Route} element={<ResetPasswordStep1 />} />
|
||||
<Route path={ResetPasswordStep2Route} element={<ResetPasswordStep2 />} />
|
||||
<Route path={RegisterWebauthnRoute} element={<RegisterWebauthn />} />
|
||||
<Route path={RegisterOneTimePasswordRoute} element={<RegisterOneTimePassword />} />
|
||||
<Route path={LogoutRoute} element={<SignOut />} />
|
||||
<Route path={ConsentRoute} element={<ConsentView />} />
|
||||
<Route
|
||||
path={`${IndexRoute}*`}
|
||||
element={
|
||||
<LoginPortal
|
||||
duoSelfEnrollment={getDuoSelfEnrollment()}
|
||||
rememberMe={getRememberMe()}
|
||||
resetPassword={getResetPassword()}
|
||||
resetPasswordCustomURL={getResetPasswordCustomURL()}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
</Router>
|
||||
</NotificationsContext.Provider>
|
||||
</Suspense>
|
||||
</ThemeProvider>
|
||||
</CacheProvider>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React from "react";
|
||||
|
||||
import { Link } from "@material-ui/core";
|
||||
import { Box, Link, Theme } from "@mui/material";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
|
||||
import AppleStore from "@assets/images/applestore-badge.svg";
|
||||
import GooglePlay from "@assets/images/googleplay-badge.svg";
|
||||
|
@ -17,17 +18,21 @@ export interface Props {
|
|||
const AppStoreBadges = function (props: Props) {
|
||||
const target = props.targetBlank ? "_blank" : undefined;
|
||||
|
||||
const width = props.iconSize;
|
||||
const styles = makeStyles((theme: Theme) => ({
|
||||
badge: {
|
||||
width: props.iconSize,
|
||||
},
|
||||
}))();
|
||||
|
||||
return (
|
||||
<div className={props.className}>
|
||||
<Link href={props.googlePlayLink} target={target}>
|
||||
<img src={GooglePlay} alt="google play" style={{ width }} />
|
||||
<Box className={props.className}>
|
||||
<Link href={props.googlePlayLink} target={target} underline="hover">
|
||||
<img src={GooglePlay} alt="google play" className={styles.badge} />
|
||||
</Link>
|
||||
<Link href={props.appleStoreLink} target={target}>
|
||||
<img src={AppleStore} alt="apple store" style={{ width }} />
|
||||
<Link href={props.appleStoreLink} target={target} underline="hover">
|
||||
<img src={AppleStore} alt="apple store" className={styles.badge} />
|
||||
</Link>
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
import React from "react";
|
||||
|
||||
import { render, screen } from "@testing-library/react";
|
||||
|
||||
import ColoredSnackbarContent from "@components/ColoredSnackbarContent";
|
||||
|
||||
it("renders without crashing", () => {
|
||||
render(<ColoredSnackbarContent level="success" message="" />);
|
||||
expect(screen.getByRole("alert")).toHaveTextContent("");
|
||||
});
|
||||
|
||||
it("should contain the message", () => {
|
||||
render(<ColoredSnackbarContent level="success" message="this is a success" />);
|
||||
expect(screen.getByRole("alert")).toHaveTextContent("this is a success");
|
||||
});
|
|
@ -1,73 +0,0 @@
|
|||
import React from "react";
|
||||
|
||||
import { makeStyles, SnackbarContent } from "@material-ui/core";
|
||||
import { amber, green } from "@material-ui/core/colors";
|
||||
import { SnackbarContentProps } from "@material-ui/core/SnackbarContent";
|
||||
import CheckCircleIcon from "@material-ui/icons/CheckCircle";
|
||||
import ErrorIcon from "@material-ui/icons/Error";
|
||||
import InfoIcon from "@material-ui/icons/Info";
|
||||
import WarningIcon from "@material-ui/icons/Warning";
|
||||
import classnames from "classnames";
|
||||
|
||||
const variantIcon = {
|
||||
success: CheckCircleIcon,
|
||||
warning: WarningIcon,
|
||||
error: ErrorIcon,
|
||||
info: InfoIcon,
|
||||
};
|
||||
|
||||
export type Level = keyof typeof variantIcon;
|
||||
|
||||
export interface Props extends SnackbarContentProps {
|
||||
className?: string;
|
||||
level: Level;
|
||||
message: string;
|
||||
}
|
||||
|
||||
const ColoredSnackbarContent = function (props: Props) {
|
||||
const classes = useStyles();
|
||||
const Icon = variantIcon[props.level];
|
||||
|
||||
const { className, variant, message, ...others } = props;
|
||||
|
||||
return (
|
||||
<SnackbarContent
|
||||
className={classnames(classes[props.level], className)}
|
||||
message={
|
||||
<span className={classes.message}>
|
||||
<Icon className={classnames(classes.icon, classes.iconVariant)} />
|
||||
{message}
|
||||
</span>
|
||||
}
|
||||
{...others}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default ColoredSnackbarContent;
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
success: {
|
||||
backgroundColor: green[600],
|
||||
},
|
||||
error: {
|
||||
backgroundColor: theme.palette.error.dark,
|
||||
},
|
||||
info: {
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
},
|
||||
warning: {
|
||||
backgroundColor: amber[700],
|
||||
},
|
||||
icon: {
|
||||
fontSize: 20,
|
||||
},
|
||||
iconVariant: {
|
||||
opacity: 0.9,
|
||||
marginRight: theme.spacing(1),
|
||||
},
|
||||
message: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
},
|
||||
}));
|
|
@ -1,9 +1,15 @@
|
|||
import React from "react";
|
||||
|
||||
import { createTheme } from "@mui/material/styles";
|
||||
import { ThemeProvider } from "@mui/styles";
|
||||
import { render } from "@testing-library/react";
|
||||
|
||||
import FixedTextField from "@components/FixedTextField";
|
||||
|
||||
it("renders without crashing", () => {
|
||||
render(<FixedTextField />);
|
||||
render(
|
||||
<ThemeProvider theme={createTheme()}>
|
||||
<FixedTextField />
|
||||
</ThemeProvider>,
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import React from "react";
|
||||
|
||||
import { makeStyles } from "@material-ui/core";
|
||||
import TextField, { TextFieldProps } from "@material-ui/core/TextField";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import TextField, { TextFieldProps } from "@mui/material/TextField";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
|
||||
/**
|
||||
* This component fixes outlined TextField
|
||||
|
@ -10,16 +11,16 @@ import TextField, { TextFieldProps } from "@material-ui/core/TextField";
|
|||
* @param props the TextField props
|
||||
*/
|
||||
const FixedTextField = function (props: TextFieldProps) {
|
||||
const style = useStyles();
|
||||
const styles = useStyles();
|
||||
|
||||
return (
|
||||
<TextField
|
||||
{...props}
|
||||
InputLabelProps={{
|
||||
classes: {
|
||||
root: style.label,
|
||||
root: styles.label,
|
||||
},
|
||||
}}
|
||||
inputProps={{ autoCapitalize: props.autoCapitalize }}
|
||||
>
|
||||
{props.children}
|
||||
</TextField>
|
||||
|
@ -28,7 +29,7 @@ const FixedTextField = function (props: TextFieldProps) {
|
|||
|
||||
export default FixedTextField;
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
label: {
|
||||
backgroundColor: theme.palette.background.default,
|
||||
paddingLeft: theme.spacing(0.1),
|
||||
|
|
|
@ -1,13 +1,23 @@
|
|||
import React from "react";
|
||||
|
||||
import { createTheme } from "@mui/material/styles";
|
||||
import { ThemeProvider } from "@mui/styles";
|
||||
import { render } from "@testing-library/react";
|
||||
|
||||
import LinearProgressBar from "@components/LinearProgressBar";
|
||||
|
||||
it("renders without crashing", () => {
|
||||
render(<LinearProgressBar value={40} />);
|
||||
render(
|
||||
<ThemeProvider theme={createTheme()}>
|
||||
<LinearProgressBar value={40} />)
|
||||
</ThemeProvider>,
|
||||
);
|
||||
});
|
||||
|
||||
it("renders adjusted height without crashing", () => {
|
||||
render(<LinearProgressBar value={40} height={2} />);
|
||||
render(
|
||||
<ThemeProvider theme={createTheme()}>
|
||||
<LinearProgressBar value={40} height={2} />
|
||||
</ThemeProvider>,
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
import React from "react";
|
||||
|
||||
import { makeStyles, LinearProgress } from "@material-ui/core";
|
||||
import { CSSProperties } from "@material-ui/styles";
|
||||
import { LinearProgress, Theme } from "@mui/material";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
|
||||
export interface Props {
|
||||
value: number;
|
||||
height?: number;
|
||||
height?: string | number;
|
||||
className?: string;
|
||||
style?: CSSProperties;
|
||||
}
|
||||
|
||||
const LinearProgressBar = function (props: Props) {
|
||||
const style = makeStyles((theme) => ({
|
||||
const styles = makeStyles((theme: Theme) => ({
|
||||
progressRoot: {
|
||||
height: props.height ? props.height : theme.spacing(),
|
||||
},
|
||||
|
@ -19,13 +18,13 @@ const LinearProgressBar = function (props: Props) {
|
|||
transition: "transform .2s linear",
|
||||
},
|
||||
}))();
|
||||
|
||||
return (
|
||||
<LinearProgress
|
||||
style={props.style as React.CSSProperties}
|
||||
variant="determinate"
|
||||
classes={{
|
||||
root: style.progressRoot,
|
||||
bar1Determinate: style.transition,
|
||||
root: styles.progressRoot,
|
||||
bar1Determinate: styles.transition,
|
||||
}}
|
||||
value={props.value}
|
||||
className={props.className}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
|
||||
import { Snackbar } from "@material-ui/core";
|
||||
import { Alert, Slide, SlideProps, Snackbar } from "@mui/material";
|
||||
|
||||
import ColoredSnackbarContent from "@components/ColoredSnackbarContent";
|
||||
import { useNotifications } from "@hooks/NotificationsContext";
|
||||
import { Notification } from "@models/Notifications";
|
||||
|
||||
|
@ -10,12 +9,18 @@ export interface Props {
|
|||
onClose: () => void;
|
||||
}
|
||||
|
||||
type NotificationBarTransitionProps = Omit<SlideProps, "direction">;
|
||||
|
||||
function NotificationBarTransition(props: NotificationBarTransitionProps) {
|
||||
return <Slide {...props} direction={"left"} />;
|
||||
}
|
||||
|
||||
const NotificationBar = function (props: Props) {
|
||||
const [tmpNotification, setTmpNotification] = useState(null as Notification | null);
|
||||
const { notification } = useNotifications();
|
||||
|
||||
useEffect(() => {
|
||||
if (notification && notification !== null) {
|
||||
if (notification) {
|
||||
setTmpNotification(notification);
|
||||
}
|
||||
}, [notification, setTmpNotification]);
|
||||
|
@ -28,15 +33,18 @@ const NotificationBar = function (props: Props) {
|
|||
anchorOrigin={{ vertical: "top", horizontal: "right" }}
|
||||
autoHideDuration={tmpNotification ? tmpNotification.timeout * 1000 : 10000}
|
||||
onClose={props.onClose}
|
||||
TransitionComponent={NotificationBarTransition}
|
||||
TransitionProps={{
|
||||
onExited: () => setTmpNotification(null),
|
||||
}}
|
||||
>
|
||||
<ColoredSnackbarContent
|
||||
className="notification"
|
||||
level={tmpNotification ? tmpNotification.level : "info"}
|
||||
message={tmpNotification ? tmpNotification.message : ""}
|
||||
/>
|
||||
{tmpNotification ? (
|
||||
<Alert severity={tmpNotification.level} variant={"filled"} elevation={6} className={"notification"}>
|
||||
{tmpNotification.message}
|
||||
</Alert>
|
||||
) : (
|
||||
<Alert severity={"success"} elevation={6} variant={"filled"} className={"notification"} />
|
||||
)}
|
||||
</Snackbar>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
|
||||
import { makeStyles } from "@material-ui/core";
|
||||
import { Box, Theme } from "@mui/material";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import classnames from "classnames";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import zxcvbn from "zxcvbn";
|
||||
|
@ -13,20 +14,12 @@ export interface Props {
|
|||
}
|
||||
|
||||
const PasswordMeter = function (props: Props) {
|
||||
const { t: translate } = useTranslation();
|
||||
|
||||
const [progressColor] = useState(["#D32F2F", "#FF5722", "#FFEB3B", "#AFB42B", "#62D32F"]);
|
||||
const [passwordScore, setPasswordScore] = useState(0);
|
||||
const [maxScores, setMaxScores] = useState(0);
|
||||
const [feedback, setFeedback] = useState("");
|
||||
const { t: translate } = useTranslation();
|
||||
const style = makeStyles((theme) => ({
|
||||
progressBar: {
|
||||
height: "5px",
|
||||
marginTop: "2px",
|
||||
backgroundColor: "red",
|
||||
width: "50%",
|
||||
transition: "width .5s linear",
|
||||
},
|
||||
}))();
|
||||
|
||||
useEffect(() => {
|
||||
const password = props.value;
|
||||
|
@ -106,17 +99,23 @@ const PasswordMeter = function (props: Props) {
|
|||
}
|
||||
}, [props, translate]);
|
||||
|
||||
const styles = makeStyles((theme: Theme) => ({
|
||||
progressBar: {
|
||||
height: "5px",
|
||||
marginTop: "2px",
|
||||
backgroundColor: progressColor[passwordScore],
|
||||
width: `${(passwordScore + 1) * (100 / maxScores)}%`,
|
||||
transition: "width .5s linear",
|
||||
},
|
||||
progressContainer: {
|
||||
width: "100%",
|
||||
},
|
||||
}))();
|
||||
|
||||
return (
|
||||
<div style={{ width: "100%" }}>
|
||||
<div
|
||||
title={feedback}
|
||||
className={classnames(style.progressBar)}
|
||||
style={{
|
||||
width: `${(passwordScore + 1) * (100 / maxScores)}%`,
|
||||
backgroundColor: progressColor[passwordScore],
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<Box className={styles.progressContainer}>
|
||||
<Box title={feedback} className={classnames(styles.progressBar)} />
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,32 +1,25 @@
|
|||
import React, { Fragment } from "react";
|
||||
|
||||
import { Tooltip, Typography } from "@material-ui/core";
|
||||
import { Variant } from "@material-ui/core/styles/createTypography";
|
||||
import { CSSProperties } from "@material-ui/styles";
|
||||
import { Tooltip, Typography } from "@mui/material";
|
||||
import { Variant } from "@mui/material/styles/createTypography";
|
||||
|
||||
export interface Props {
|
||||
variant: Variant;
|
||||
|
||||
value?: string;
|
||||
style?: CSSProperties;
|
||||
|
||||
tooltip?: string;
|
||||
tooltipStyle?: CSSProperties;
|
||||
}
|
||||
|
||||
export default function TypographyWithTooltip(props: Props): JSX.Element {
|
||||
return (
|
||||
<Fragment>
|
||||
{props.tooltip ? (
|
||||
<Tooltip title={props.tooltip} style={props.tooltipStyle}>
|
||||
<Typography variant={props.variant} style={props.style}>
|
||||
{props.value}
|
||||
</Typography>
|
||||
<Tooltip title={props.tooltip}>
|
||||
<Typography variant={props.variant}>{props.value}</Typography>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<Typography variant={props.variant} style={props.style}>
|
||||
{props.value}
|
||||
</Typography>
|
||||
<Typography variant={props.variant}>{props.value}</Typography>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { createContext, useContext, useRef } from "react";
|
||||
|
||||
import { Level } from "@components/ColoredSnackbarContent";
|
||||
import { AlertColor } from "@mui/material";
|
||||
|
||||
import { Notification } from "@models/Notifications";
|
||||
|
||||
const defaultOptions = {
|
||||
|
@ -19,7 +20,7 @@ export default NotificationsContext;
|
|||
export function useNotifications() {
|
||||
let useNotificationsProps = useContext(NotificationsContext);
|
||||
|
||||
const notificationBuilder = (level: Level) => {
|
||||
const notificationBuilder = (level: AlertColor) => {
|
||||
return (message: string, timeout?: number) => {
|
||||
useNotificationsProps.setNotification({
|
||||
level,
|
||||
|
|
|
@ -7,8 +7,9 @@ import App from "@root/App";
|
|||
import * as serviceWorker from "@root/serviceWorker";
|
||||
import "@i18n/index.ts";
|
||||
|
||||
const nonce = document.head.querySelector("[property=csp-nonce][content]")?.getAttribute("content") || undefined;
|
||||
const root = createRoot(document.getElementById("root")!);
|
||||
root.render(<App />);
|
||||
root.render(<App nonce={nonce} />);
|
||||
|
||||
// If you want your app to work offline and load faster, you can change
|
||||
// unregister() to register() below. Note this comes with some pitfalls.
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import React, { ReactNode, useEffect } from "react";
|
||||
|
||||
import { Grid, makeStyles, Container, Link } from "@material-ui/core";
|
||||
import { grey } from "@material-ui/core/colors";
|
||||
import { Grid, Container, Link, Theme } from "@mui/material";
|
||||
import { grey } from "@mui/material/colors";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { ReactComponent as UserSvg } from "@assets/images/user.svg";
|
||||
|
@ -18,20 +19,22 @@ export interface Props {
|
|||
showBrand?: boolean;
|
||||
}
|
||||
|
||||
const url = "https://www.authelia.com";
|
||||
|
||||
const LoginLayout = function (props: Props) {
|
||||
const style = useStyles();
|
||||
const styles = useStyles();
|
||||
const logo = getLogoOverride() ? (
|
||||
<img src="./static/media/logo.png" alt="Logo" className={style.icon} />
|
||||
<img src="./static/media/logo.png" alt="Logo" className={styles.icon} />
|
||||
) : (
|
||||
<UserSvg className={style.icon} />
|
||||
<UserSvg className={styles.icon} />
|
||||
);
|
||||
const { t: translate } = useTranslation();
|
||||
useEffect(() => {
|
||||
document.title = `${translate("Login")} - Authelia`;
|
||||
}, [translate]);
|
||||
return (
|
||||
<Grid id={props.id} className={style.root} container spacing={0} alignItems="center" justifyContent="center">
|
||||
<Container maxWidth="xs" className={style.rootContainer}>
|
||||
<Grid id={props.id} className={styles.root} container spacing={0} alignItems="center" justifyContent="center">
|
||||
<Container maxWidth="xs" className={styles.rootContainer}>
|
||||
<Grid container>
|
||||
<Grid item xs={12}>
|
||||
{logo}
|
||||
|
@ -50,16 +53,12 @@ const LoginLayout = function (props: Props) {
|
|||
/>
|
||||
</Grid>
|
||||
) : null}
|
||||
<Grid item xs={12} className={style.body}>
|
||||
<Grid item xs={12} className={styles.body}>
|
||||
{props.children}
|
||||
</Grid>
|
||||
{props.showBrand ? (
|
||||
<Grid item xs={12}>
|
||||
<Link
|
||||
href="https://github.com/authelia/authelia"
|
||||
target="_blank"
|
||||
className={style.poweredBy}
|
||||
>
|
||||
<Link href={url} target="_blank" underline="hover" className={styles.poweredBy}>
|
||||
{translate("Powered by")} Authelia
|
||||
</Link>
|
||||
</Grid>
|
||||
|
@ -72,7 +71,7 @@ const LoginLayout = function (props: Props) {
|
|||
|
||||
export default LoginLayout;
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
root: {
|
||||
minHeight: "90vh",
|
||||
textAlign: "center",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Level } from "@components/ColoredSnackbarContent";
|
||||
import { AlertColor } from "@mui/material";
|
||||
|
||||
export interface Notification {
|
||||
message: string;
|
||||
level: Level;
|
||||
level: AlertColor;
|
||||
timeout: number;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { createTheme } from "@material-ui/core/styles";
|
||||
import { createTheme } from "@mui/material/styles";
|
||||
|
||||
const Dark = createTheme({
|
||||
custom: {
|
||||
|
@ -6,10 +6,81 @@ const Dark = createTheme({
|
|||
loadingBar: "#fff",
|
||||
},
|
||||
palette: {
|
||||
type: "dark",
|
||||
mode: "dark",
|
||||
primary: {
|
||||
main: "#1976d2",
|
||||
},
|
||||
secondary: {
|
||||
light: "#ff4081",
|
||||
main: "#f50057",
|
||||
dark: "#c51162",
|
||||
contrastText: "#ffffff",
|
||||
},
|
||||
error: {
|
||||
light: "#e57373",
|
||||
main: "#f44336",
|
||||
dark: "#d32f2f",
|
||||
contrastText: "#ffffff",
|
||||
},
|
||||
warning: {
|
||||
light: "#ffb74d",
|
||||
main: "#ff9800",
|
||||
dark: "#f57c00",
|
||||
contrastText: "rgba(0, 0, 0, 0.87)",
|
||||
},
|
||||
info: {
|
||||
light: "#64b5f6",
|
||||
main: "#2196f3",
|
||||
dark: "#1976d2",
|
||||
contrastText: "#ffffff",
|
||||
},
|
||||
success: {
|
||||
light: "#81c784",
|
||||
main: "#4caf50",
|
||||
dark: "#388e3c",
|
||||
contrastText: "rgba(0, 0, 0, 0.87)",
|
||||
},
|
||||
grey: {
|
||||
"50": "#fafafa",
|
||||
"100": "#f5f5f5",
|
||||
"200": "#eeeeee",
|
||||
"300": "#e0e0e0",
|
||||
"400": "#bdbdbd",
|
||||
"500": "#9e9e9e",
|
||||
"600": "#757575",
|
||||
"700": "#616161",
|
||||
"800": "#424242",
|
||||
"900": "#212121",
|
||||
A100: "#d5d5d5",
|
||||
A200: "#aaaaaa",
|
||||
A400: "#303030",
|
||||
A700: "#616161",
|
||||
},
|
||||
contrastThreshold: 3,
|
||||
tonalOffset: 0.2,
|
||||
text: {
|
||||
primary: "#fff",
|
||||
secondary: "rgba(255, 255, 255, 0.7)",
|
||||
disabled: "rgba(255, 255, 255, 0.5)",
|
||||
},
|
||||
divider: "rgba(255, 255, 255, 0.12)",
|
||||
background: {
|
||||
paper: "#424242",
|
||||
default: "#303030",
|
||||
},
|
||||
action: {
|
||||
active: "#fff",
|
||||
hover: "rgba(255, 255, 255, 0.08)",
|
||||
hoverOpacity: 0.08,
|
||||
selected: "rgba(255, 255, 255, 0.16)",
|
||||
selectedOpacity: 0.16,
|
||||
disabled: "rgba(255, 255, 255, 0.3)",
|
||||
disabledBackground: "rgba(255, 255, 255, 0.12)",
|
||||
disabledOpacity: 0.38,
|
||||
focus: "rgba(255, 255, 255, 0.12)",
|
||||
focusOpacity: 0.12,
|
||||
activatedOpacity: 0.24,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { createTheme } from "@material-ui/core/styles";
|
||||
import { createTheme } from "@mui/material/styles";
|
||||
|
||||
const Grey = createTheme({
|
||||
custom: {
|
||||
|
@ -6,51 +6,129 @@ const Grey = createTheme({
|
|||
loadingBar: "#929aa5",
|
||||
},
|
||||
palette: {
|
||||
mode: "dark",
|
||||
primary: {
|
||||
main: "#929aa5",
|
||||
},
|
||||
secondary: {
|
||||
light: "#ff4081",
|
||||
main: "#f50057",
|
||||
dark: "#c51162",
|
||||
contrastText: "#ffffff",
|
||||
},
|
||||
error: {
|
||||
light: "#e57373",
|
||||
main: "#f44336",
|
||||
dark: "#d32f2f",
|
||||
contrastText: "#ffffff",
|
||||
},
|
||||
warning: {
|
||||
light: "#ffb74d",
|
||||
main: "#ff9800",
|
||||
dark: "#f57c00",
|
||||
contrastText: "rgba(0, 0, 0, 0.87)",
|
||||
},
|
||||
info: {
|
||||
light: "#64b5f6",
|
||||
main: "#2196f3",
|
||||
dark: "#1976d2",
|
||||
contrastText: "#ffffff",
|
||||
},
|
||||
success: {
|
||||
light: "#81c784",
|
||||
main: "#4caf50",
|
||||
dark: "#388e3c",
|
||||
contrastText: "rgba(0, 0, 0, 0.87)",
|
||||
},
|
||||
grey: {
|
||||
"50": "#fafafa",
|
||||
"100": "#f5f5f5",
|
||||
"200": "#eeeeee",
|
||||
"300": "#e0e0e0",
|
||||
"400": "#bdbdbd",
|
||||
"500": "#9e9e9e",
|
||||
"600": "#757575",
|
||||
"700": "#616161",
|
||||
"800": "#424242",
|
||||
"900": "#212121",
|
||||
A100: "#d5d5d5",
|
||||
A200: "#aaaaaa",
|
||||
A400: "#303030",
|
||||
A700: "#616161",
|
||||
},
|
||||
contrastThreshold: 3,
|
||||
tonalOffset: 0.2,
|
||||
text: {
|
||||
primary: "#929aa5",
|
||||
secondary: "rgba(0, 0, 0, 0.54)",
|
||||
disabled: "rgba(0, 0, 0, 0.38)",
|
||||
},
|
||||
divider: "rgba(0, 0, 0, 0.12)",
|
||||
background: {
|
||||
default: "#2f343e",
|
||||
paper: "#2f343e",
|
||||
default: "#2f343e",
|
||||
},
|
||||
action: {
|
||||
active: "#929aa5",
|
||||
hover: "#929aa5",
|
||||
hoverOpacity: 0.04,
|
||||
selected: "#929aa5",
|
||||
selectedOpacity: 0.08,
|
||||
disabled: "rgba(0, 0, 0, 0.26)",
|
||||
disabledBackground: "rgba(0, 0, 0, 0.12)",
|
||||
disabledOpacity: 0.38,
|
||||
focus: "rgba(0, 0, 0, 0.12)",
|
||||
focusOpacity: 0.12,
|
||||
activatedOpacity: 0.12,
|
||||
},
|
||||
},
|
||||
overrides: {
|
||||
components: {
|
||||
MuiCssBaseline: {
|
||||
"@global": {
|
||||
body: {
|
||||
backgroundColor: "#2f343e",
|
||||
color: "#929aa5",
|
||||
styleOverrides: {
|
||||
"@global": {
|
||||
body: {
|
||||
backgroundColor: "#2f343e",
|
||||
color: "#929aa5",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiOutlinedInput: {
|
||||
root: {
|
||||
"& $notchedOutline": {
|
||||
borderColor: "#929aa5",
|
||||
},
|
||||
"&:hover:not($disabled):not($focused):not($error) $notchedOutline": {
|
||||
borderColor: "#929aa5",
|
||||
borderWidth: 2,
|
||||
},
|
||||
"&$focused $notchedOutline": {
|
||||
borderColor: "#929aa5",
|
||||
styleOverrides: {
|
||||
root: {
|
||||
"& $notchedOutline": {
|
||||
borderColor: "#929aa5",
|
||||
},
|
||||
"&:hover:not($disabled):not($focused):not($error) $notchedOutline": {
|
||||
borderColor: "#929aa5",
|
||||
borderWidth: 2,
|
||||
},
|
||||
"&$focused $notchedOutline": {
|
||||
borderColor: "#929aa5",
|
||||
},
|
||||
},
|
||||
notchedOutline: {},
|
||||
},
|
||||
notchedOutline: {},
|
||||
},
|
||||
MuiCheckbox: {
|
||||
root: {
|
||||
color: "#929aa5",
|
||||
styleOverrides: {
|
||||
root: {
|
||||
color: "#929aa5",
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiInputBase: {
|
||||
input: {
|
||||
color: "#929aa5",
|
||||
styleOverrides: {
|
||||
input: {
|
||||
color: "#929aa5",
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiInputLabel: {
|
||||
root: {
|
||||
color: "#929aa5",
|
||||
styleOverrides: {
|
||||
root: {
|
||||
color: "#929aa5",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { createTheme } from "@material-ui/core/styles";
|
||||
import { createTheme } from "@mui/material/styles";
|
||||
|
||||
const Light = createTheme({
|
||||
custom: {
|
||||
|
@ -6,12 +6,80 @@ const Light = createTheme({
|
|||
loadingBar: "#000",
|
||||
},
|
||||
palette: {
|
||||
mode: "light",
|
||||
primary: {
|
||||
main: "#1976d2",
|
||||
},
|
||||
secondary: {
|
||||
light: "#ff4081",
|
||||
main: "#f50057",
|
||||
dark: "#c51162",
|
||||
contrastText: "#ffffff",
|
||||
},
|
||||
error: {
|
||||
light: "#e57373",
|
||||
main: "#f44336",
|
||||
dark: "#d32f2f",
|
||||
contrastText: "#ffffff",
|
||||
},
|
||||
warning: {
|
||||
light: "#ffb74d",
|
||||
main: "#ff9800",
|
||||
dark: "#f57c00",
|
||||
contrastText: "rgba(0, 0, 0, 0.87)",
|
||||
},
|
||||
info: {
|
||||
light: "#64b5f6",
|
||||
main: "#2196f3",
|
||||
dark: "#1976d2",
|
||||
contrastText: "#ffffff",
|
||||
},
|
||||
success: {
|
||||
light: "#81c784",
|
||||
main: "#4caf50",
|
||||
dark: "#388e3c",
|
||||
contrastText: "rgba(0, 0, 0, 0.87)",
|
||||
},
|
||||
grey: {
|
||||
"50": "#fafafa",
|
||||
"100": "#f5f5f5",
|
||||
"200": "#eeeeee",
|
||||
"300": "#e0e0e0",
|
||||
"400": "#bdbdbd",
|
||||
"500": "#9e9e9e",
|
||||
"600": "#757575",
|
||||
"700": "#616161",
|
||||
"800": "#424242",
|
||||
"900": "#212121",
|
||||
A100: "#d5d5d5",
|
||||
A200: "#aaaaaa",
|
||||
A400: "#303030",
|
||||
A700: "#616161",
|
||||
},
|
||||
contrastThreshold: 3,
|
||||
tonalOffset: 0.2,
|
||||
text: {
|
||||
primary: "rgba(0, 0, 0, 0.87)",
|
||||
secondary: "rgba(0, 0, 0, 0.54)",
|
||||
disabled: "rgba(0, 0, 0, 0.38)",
|
||||
},
|
||||
divider: "rgba(0, 0, 0, 0.12)",
|
||||
background: {
|
||||
default: "#fff",
|
||||
paper: "#fff",
|
||||
default: "#fff",
|
||||
},
|
||||
action: {
|
||||
active: "rgba(0, 0, 0, 0.54)",
|
||||
hover: "rgba(0, 0, 0, 0.04)",
|
||||
hoverOpacity: 0.04,
|
||||
selected: "rgba(0, 0, 0, 0.08)",
|
||||
selectedOpacity: 0.08,
|
||||
disabled: "rgba(0, 0, 0, 0.26)",
|
||||
disabledBackground: "rgba(0, 0, 0, 0.12)",
|
||||
disabledOpacity: 0.38,
|
||||
focus: "rgba(0, 0, 0, 0.12)",
|
||||
focusOpacity: 0.12,
|
||||
activatedOpacity: 0.12,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,18 +1,28 @@
|
|||
declare module "@material-ui/core/styles/createTheme" {
|
||||
import React from "react";
|
||||
|
||||
import { Theme } from "@mui/material";
|
||||
|
||||
declare module "@mui/material/styles" {
|
||||
interface Theme {
|
||||
custom: {
|
||||
icon: React.CSSProperties["color"];
|
||||
loadingBar: React.CSSProperties["color"];
|
||||
};
|
||||
}
|
||||
|
||||
interface ThemeOptions {
|
||||
custom: {
|
||||
icon: React.CSSProperties["color"];
|
||||
loadingBar: React.CSSProperties["color"];
|
||||
custom?: {
|
||||
icon?: React.CSSProperties["color"];
|
||||
loadingBar?: React.CSSProperties["color"];
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
declare module "@mui/styles/defaultTheme" {
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
interface DefaultTheme extends Theme {}
|
||||
}
|
||||
|
||||
export { default as Light } from "@themes/Light";
|
||||
export { default as Dark } from "@themes/Dark";
|
||||
export { default as Grey } from "@themes/Grey";
|
||||
|
|
|
@ -2,10 +2,11 @@ import React, { useEffect, useCallback, useState } from "react";
|
|||
|
||||
import { IconDefinition, faCopy, faKey, faTimesCircle } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { makeStyles, Typography, Button, IconButton, Link, CircularProgress, TextField } from "@material-ui/core";
|
||||
import { red } from "@material-ui/core/colors";
|
||||
import { Typography, Button, IconButton, Link, CircularProgress, TextField, Theme } from "@mui/material";
|
||||
import { red } from "@mui/material/colors";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import classnames from "classnames";
|
||||
import QRCode from "qrcode.react";
|
||||
import { QRCodeSVG } from "qrcode.react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
|
||||
|
@ -18,7 +19,7 @@ import { completeTOTPRegistrationProcess } from "@services/RegisterDevice";
|
|||
import { extractIdentityToken } from "@utils/IdentityToken";
|
||||
|
||||
const RegisterOneTimePassword = function () {
|
||||
const style = useStyles();
|
||||
const styles = useStyles();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
// The secret retrieved from the API is all is ok.
|
||||
|
@ -72,39 +73,40 @@ const RegisterOneTimePassword = function () {
|
|||
function SecretButton(text: string | undefined, action: string, icon: IconDefinition) {
|
||||
return (
|
||||
<IconButton
|
||||
className={style.secretButtons}
|
||||
className={styles.secretButtons}
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(`${text}`);
|
||||
createSuccessNotification(`${action}`);
|
||||
}}
|
||||
size="large"
|
||||
>
|
||||
<FontAwesomeIcon icon={icon} />
|
||||
</IconButton>
|
||||
);
|
||||
}
|
||||
const qrcodeFuzzyStyle = isLoading || hasErrored ? style.fuzzy : undefined;
|
||||
const qrcodeFuzzyStyle = isLoading || hasErrored ? styles.fuzzy : undefined;
|
||||
|
||||
return (
|
||||
<LoginLayout title={translate("Scan QR Code")}>
|
||||
<div className={style.root}>
|
||||
<div className={style.googleAuthenticator}>
|
||||
<Typography className={style.googleAuthenticatorText}>
|
||||
<div className={styles.root}>
|
||||
<div className={styles.googleAuthenticator}>
|
||||
<Typography className={styles.googleAuthenticatorText}>
|
||||
{translate("Need Google Authenticator?")}
|
||||
</Typography>
|
||||
<AppStoreBadges
|
||||
iconSize={128}
|
||||
targetBlank
|
||||
className={style.googleAuthenticatorBadges}
|
||||
className={styles.googleAuthenticatorBadges}
|
||||
googlePlayLink={GoogleAuthenticator.googlePlay}
|
||||
appleStoreLink={GoogleAuthenticator.appleStore}
|
||||
/>
|
||||
</div>
|
||||
<div className={classnames(qrcodeFuzzyStyle, style.qrcodeContainer)}>
|
||||
<Link href={secretURL}>
|
||||
<QRCode value={secretURL} className={style.qrcode} size={256} />
|
||||
{!hasErrored && isLoading ? <CircularProgress className={style.loader} size={128} /> : null}
|
||||
{hasErrored ? <FontAwesomeIcon className={style.failureIcon} icon={faTimesCircle} /> : null}
|
||||
<div className={classnames(qrcodeFuzzyStyle, styles.qrcodeContainer)}>
|
||||
<Link href={secretURL} underline="hover">
|
||||
<QRCodeSVG value={secretURL} className={styles.qrcode} size={256} />
|
||||
{!hasErrored && isLoading ? <CircularProgress className={styles.loader} size={128} /> : null}
|
||||
{hasErrored ? <FontAwesomeIcon className={styles.failureIcon} icon={faTimesCircle} /> : null}
|
||||
</Link>
|
||||
</div>
|
||||
<div>
|
||||
|
@ -112,7 +114,7 @@ const RegisterOneTimePassword = function () {
|
|||
<TextField
|
||||
id="secret-url"
|
||||
label={translate("Secret")}
|
||||
className={style.secret}
|
||||
className={styles.secret}
|
||||
value={secretURL}
|
||||
InputProps={{
|
||||
readOnly: true,
|
||||
|
@ -129,7 +131,7 @@ const RegisterOneTimePassword = function () {
|
|||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
className={style.doneButton}
|
||||
className={styles.doneButton}
|
||||
onClick={handleDoneClick}
|
||||
disabled={isLoading}
|
||||
>
|
||||
|
@ -142,7 +144,7 @@ const RegisterOneTimePassword = function () {
|
|||
|
||||
export default RegisterOneTimePassword;
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
root: {
|
||||
paddingTop: theme.spacing(4),
|
||||
paddingBottom: theme.spacing(4),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useCallback, useEffect, useState } from "react";
|
||||
|
||||
import { Button, makeStyles, Typography } from "@material-ui/core";
|
||||
import { Button, Theme, Typography } from "@mui/material";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
|
||||
import FingerTouchIcon from "@components/FingerTouchIcon";
|
||||
|
@ -12,7 +13,7 @@ import { performAttestationCeremony } from "@services/Webauthn";
|
|||
import { extractIdentityToken } from "@utils/IdentityToken";
|
||||
|
||||
const RegisterWebauthn = function () {
|
||||
const style = useStyles();
|
||||
const styles = useStyles();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const { createErrorNotification } = useNotifications();
|
||||
|
@ -84,10 +85,10 @@ const RegisterWebauthn = function () {
|
|||
|
||||
return (
|
||||
<LoginLayout title="Touch Security Key">
|
||||
<div className={style.icon}>
|
||||
<div className={styles.icon}>
|
||||
<FingerTouchIcon size={64} animated />
|
||||
</div>
|
||||
<Typography className={style.instruction}>Touch the token on your security key</Typography>
|
||||
<Typography className={styles.instruction}>Touch the token on your security key</Typography>
|
||||
<Button color="primary" onClick={handleBackClick}>
|
||||
Retry
|
||||
</Button>
|
||||
|
@ -100,7 +101,7 @@ const RegisterWebauthn = function () {
|
|||
|
||||
export default RegisterWebauthn;
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
icon: {
|
||||
paddingTop: theme.spacing(4),
|
||||
paddingBottom: theme.spacing(4),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React from "react";
|
||||
|
||||
import { Grid, Typography, useTheme } from "@material-ui/core";
|
||||
import { Grid, Theme, Typography, useTheme } from "@mui/material";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import ReactLoading from "react-loading";
|
||||
|
||||
export interface Props {
|
||||
|
@ -9,9 +10,11 @@ export interface Props {
|
|||
|
||||
const BaseLoadingPage = function (props: Props) {
|
||||
const theme = useTheme();
|
||||
const styles = useStyles();
|
||||
|
||||
return (
|
||||
<Grid container alignItems="center" justifyContent="center" style={{ minHeight: "100vh" }}>
|
||||
<Grid item style={{ textAlign: "center", display: "inline-block" }}>
|
||||
<Grid container className={styles.gridOuter}>
|
||||
<Grid item className={styles.gridInner}>
|
||||
<ReactLoading width={64} height={64} color={theme.custom.loadingBar} type="bars" />
|
||||
<Typography>{props.message}...</Typography>
|
||||
</Grid>
|
||||
|
@ -20,3 +23,15 @@ const BaseLoadingPage = function (props: Props) {
|
|||
};
|
||||
|
||||
export default BaseLoadingPage;
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
gridOuter: {
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
minHeight: "100vh",
|
||||
},
|
||||
gridInner: {
|
||||
textAlign: "center",
|
||||
display: "inline-block",
|
||||
},
|
||||
}));
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
import React from "react";
|
||||
|
||||
import { Typography, makeStyles } from "@material-ui/core";
|
||||
import { Theme, Typography } from "@mui/material";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import SuccessIcon from "@components/SuccessIcon";
|
||||
|
||||
const Authenticated = function () {
|
||||
const classes = useStyles();
|
||||
const styles = useStyles();
|
||||
const { t: translate } = useTranslation();
|
||||
return (
|
||||
<div id="authenticated-stage">
|
||||
<div className={classes.iconContainer}>
|
||||
<div className={styles.iconContainer}>
|
||||
<SuccessIcon />
|
||||
</div>
|
||||
<Typography>{translate("Authenticated")}</Typography>
|
||||
|
@ -20,7 +21,7 @@ const Authenticated = function () {
|
|||
|
||||
export default Authenticated;
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
iconContainer: {
|
||||
marginBottom: theme.spacing(2),
|
||||
flex: "0 0 100%",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React from "react";
|
||||
|
||||
import { Grid, makeStyles, Button } from "@material-ui/core";
|
||||
import { Grid, Button, Theme } from "@mui/material";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
|
@ -13,7 +14,7 @@ export interface Props {
|
|||
}
|
||||
|
||||
const AuthenticatedView = function (props: Props) {
|
||||
const style = useStyles();
|
||||
const styles = useStyles();
|
||||
const navigate = useNavigate();
|
||||
const { t: translate } = useTranslation();
|
||||
|
||||
|
@ -29,7 +30,7 @@ const AuthenticatedView = function (props: Props) {
|
|||
{translate("Logout")}
|
||||
</Button>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={style.mainContainer}>
|
||||
<Grid item xs={12} className={styles.mainContainer}>
|
||||
<Authenticated />
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
@ -39,7 +40,7 @@ const AuthenticatedView = function (props: Props) {
|
|||
|
||||
export default AuthenticatedView;
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
mainContainer: {
|
||||
border: "1px solid #d6d6d6",
|
||||
borderRadius: "10px",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React, { useEffect, Fragment, ReactNode, useState } from "react";
|
||||
|
||||
import { AccountBox, CheckBox, Contacts, Drafts, Group } from "@mui/icons-material";
|
||||
import {
|
||||
Button,
|
||||
Grid,
|
||||
|
@ -9,11 +10,11 @@ import {
|
|||
ListItemText,
|
||||
Tooltip,
|
||||
Typography,
|
||||
makeStyles,
|
||||
Checkbox,
|
||||
FormControlLabel,
|
||||
} from "@material-ui/core";
|
||||
import { AccountBox, CheckBox, Contacts, Drafts, Group } from "@material-ui/icons";
|
||||
Theme,
|
||||
} from "@mui/material";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
|
@ -44,7 +45,7 @@ function scopeNameToAvatar(id: string) {
|
|||
}
|
||||
|
||||
const ConsentView = function (props: Props) {
|
||||
const classes = useStyles();
|
||||
const styles = useStyles();
|
||||
const navigate = useNavigate();
|
||||
const redirect = useRedirector();
|
||||
const { createErrorNotification, resetNotification } = useNotifications();
|
||||
|
@ -137,7 +138,7 @@ const ConsentView = function (props: Props) {
|
|||
"Client ID: " + resp?.client_id
|
||||
}
|
||||
>
|
||||
<Typography className={classes.clientDescription}>
|
||||
<Typography className={styles.clientDescription}>
|
||||
{resp !== undefined && resp.client_description !== ""
|
||||
? resp.client_description
|
||||
: resp?.client_id}
|
||||
|
@ -149,8 +150,8 @@ const ConsentView = function (props: Props) {
|
|||
<div>{translate("The above application is requesting the following permissions")}:</div>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<div className={classes.scopesListContainer}>
|
||||
<List className={classes.scopesList}>
|
||||
<div className={styles.scopesListContainer}>
|
||||
<List className={styles.scopesList}>
|
||||
{resp?.scopes.map((scope: string) => (
|
||||
<Tooltip title={"Scope " + scope}>
|
||||
<ListItem id={"scope-" + scope} dense>
|
||||
|
@ -180,7 +181,7 @@ const ConsentView = function (props: Props) {
|
|||
color="primary"
|
||||
/>
|
||||
}
|
||||
className={classes.preConfigure}
|
||||
className={styles.preConfigure}
|
||||
label={translate("Remember Consent")}
|
||||
/>
|
||||
</Tooltip>
|
||||
|
@ -191,7 +192,7 @@ const ConsentView = function (props: Props) {
|
|||
<Grid item xs={6}>
|
||||
<Button
|
||||
id="accept-button"
|
||||
className={classes.button}
|
||||
className={styles.button}
|
||||
disabled={!resp}
|
||||
onClick={handleAcceptConsent}
|
||||
color="primary"
|
||||
|
@ -203,7 +204,7 @@ const ConsentView = function (props: Props) {
|
|||
<Grid item xs={6}>
|
||||
<Button
|
||||
id="deny-button"
|
||||
className={classes.button}
|
||||
className={styles.button}
|
||||
disabled={!resp}
|
||||
onClick={handleRejectConsent}
|
||||
color="secondary"
|
||||
|
@ -220,7 +221,7 @@ const ConsentView = function (props: Props) {
|
|||
);
|
||||
};
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
container: {
|
||||
paddingTop: theme.spacing(4),
|
||||
paddingBottom: theme.spacing(4),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { MutableRefObject, useEffect, useRef, useState } from "react";
|
||||
|
||||
import { makeStyles, Grid, Button, FormControlLabel, Checkbox, Link } from "@material-ui/core";
|
||||
import { Grid, Button, FormControlLabel, Checkbox, Link, Theme } from "@mui/material";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import classnames from "classnames";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
@ -29,7 +30,7 @@ export interface Props {
|
|||
}
|
||||
|
||||
const FirstFactorForm = function (props: Props) {
|
||||
const style = useStyles();
|
||||
const styles = useStyles();
|
||||
const navigate = useNavigate();
|
||||
const redirectionURL = useRedirectionURL();
|
||||
const requestMethod = useRequestMethod();
|
||||
|
@ -170,7 +171,7 @@ const FirstFactorForm = function (props: Props) {
|
|||
/>
|
||||
</Grid>
|
||||
{props.rememberMe ? (
|
||||
<Grid item xs={12} className={classnames(style.actionRow)}>
|
||||
<Grid item xs={12} className={classnames(styles.actionRow)}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
|
@ -192,7 +193,7 @@ const FirstFactorForm = function (props: Props) {
|
|||
color="primary"
|
||||
/>
|
||||
}
|
||||
className={style.rememberMe}
|
||||
className={styles.rememberMe}
|
||||
label={translate("Remember me")}
|
||||
/>
|
||||
</Grid>
|
||||
|
@ -210,12 +211,13 @@ const FirstFactorForm = function (props: Props) {
|
|||
</Button>
|
||||
</Grid>
|
||||
{props.resetPassword ? (
|
||||
<Grid item xs={12} className={classnames(style.actionRow, style.flexEnd)}>
|
||||
<Grid item xs={12} className={classnames(styles.actionRow, styles.flexEnd)}>
|
||||
<Link
|
||||
id="reset-password-button"
|
||||
component="button"
|
||||
onClick={handleResetPasswordClick}
|
||||
className={style.resetLink}
|
||||
className={styles.resetLink}
|
||||
underline="hover"
|
||||
>
|
||||
{translate("Reset password?")}
|
||||
</Link>
|
||||
|
@ -228,7 +230,7 @@ const FirstFactorForm = function (props: Props) {
|
|||
|
||||
export default FirstFactorForm;
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
actionRow: {
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { ReactNode, useState } from "react";
|
||||
|
||||
import { makeStyles, Typography, Grid, Button, Container } from "@material-ui/core";
|
||||
import { Typography, Grid, Button, Container, Theme } from "@mui/material";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
|
||||
import PushNotificationIcon from "@components/PushNotificationIcon";
|
||||
|
||||
|
@ -102,7 +103,7 @@ interface DeviceItemProps {
|
|||
function DeviceItem(props: DeviceItemProps) {
|
||||
const className = "device-option-" + props.id;
|
||||
const idName = "device-" + props.device.id;
|
||||
const style = makeStyles((theme) => ({
|
||||
const style = makeStyles((theme: Theme) => ({
|
||||
item: {
|
||||
paddingTop: theme.spacing(4),
|
||||
paddingBottom: theme.spacing(4),
|
||||
|
@ -147,7 +148,7 @@ interface MethodItemProps {
|
|||
function MethodItem(props: MethodItemProps) {
|
||||
const className = "method-option-" + props.id;
|
||||
const idName = "method-" + props.method;
|
||||
const style = makeStyles((theme) => ({
|
||||
const style = makeStyles((theme: Theme) => ({
|
||||
item: {
|
||||
paddingTop: theme.spacing(4),
|
||||
paddingBottom: theme.spacing(4),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { ReactNode } from "react";
|
||||
|
||||
import { makeStyles } from "@material-ui/core";
|
||||
import { Theme } from "@mui/material";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import classnames from "classnames";
|
||||
|
||||
interface IconWithContextProps {
|
||||
|
@ -12,7 +13,7 @@ interface IconWithContextProps {
|
|||
|
||||
const IconWithContext = function (props: IconWithContextProps) {
|
||||
const iconSize = 64;
|
||||
const style = makeStyles((theme) => ({
|
||||
const styles = makeStyles((theme: Theme) => ({
|
||||
root: {},
|
||||
iconContainer: {
|
||||
display: "flex",
|
||||
|
@ -29,11 +30,11 @@ const IconWithContext = function (props: IconWithContextProps) {
|
|||
}))();
|
||||
|
||||
return (
|
||||
<div className={classnames(props.className, style.root)}>
|
||||
<div className={style.iconContainer}>
|
||||
<div className={style.icon}>{props.icon}</div>
|
||||
<div className={classnames(props.className, styles.root)}>
|
||||
<div className={styles.iconContainer}>
|
||||
<div className={styles.icon}>{props.icon}</div>
|
||||
</div>
|
||||
<div className={style.context}>{props.children}</div>
|
||||
<div className={styles.context}>{props.children}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { ReactNode, Fragment } from "react";
|
||||
|
||||
import { makeStyles, Typography, Link, useTheme } from "@material-ui/core";
|
||||
import { Typography, Link, Theme, Box } from "@mui/material";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import classnames from "classnames";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
@ -27,7 +28,7 @@ export interface Props {
|
|||
}
|
||||
|
||||
const DefaultMethodContainer = function (props: Props) {
|
||||
const style = useStyles();
|
||||
const styles = useStyles();
|
||||
const { t: translate } = useTranslation();
|
||||
const registerMessage = props.registered
|
||||
? props.title === "Push Notification"
|
||||
|
@ -56,17 +57,17 @@ const DefaultMethodContainer = function (props: Props) {
|
|||
return (
|
||||
<div id={props.id}>
|
||||
<Typography variant="h6">{props.title}</Typography>
|
||||
<div className={classnames(style.container, stateClass)} id="2fa-container">
|
||||
<div className={style.containerFlex}>{container}</div>
|
||||
<div className={classnames(styles.container, stateClass)} id="2fa-container">
|
||||
<div className={styles.containerFlex}>{container}</div>
|
||||
</div>
|
||||
{props.onSelectClick && props.registered ? (
|
||||
<Link component="button" id="selection-link" onClick={props.onSelectClick}>
|
||||
<Link component="button" id="selection-link" onClick={props.onSelectClick} underline="hover">
|
||||
{selectMessage}
|
||||
</Link>
|
||||
) : null}
|
||||
{(props.onRegisterClick && props.title !== "Push Notification") ||
|
||||
(props.onRegisterClick && props.title === "Push Notification" && props.duoSelfEnrollment) ? (
|
||||
<Link component="button" id="register-link" onClick={props.onRegisterClick}>
|
||||
<Link component="button" id="register-link" onClick={props.onRegisterClick} underline="hover">
|
||||
{registerMessage}
|
||||
</Link>
|
||||
) : null}
|
||||
|
@ -76,7 +77,7 @@ const DefaultMethodContainer = function (props: Props) {
|
|||
|
||||
export default DefaultMethodContainer;
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
container: {
|
||||
height: "200px",
|
||||
},
|
||||
|
@ -89,6 +90,16 @@ const useStyles = makeStyles(() => ({
|
|||
alignContent: "center",
|
||||
justifyContent: "center",
|
||||
},
|
||||
containerMethod: {
|
||||
marginBottom: theme.spacing(2),
|
||||
},
|
||||
info: {
|
||||
marginBottom: theme.spacing(2),
|
||||
flex: "0 0 100%",
|
||||
},
|
||||
infoTypography: {
|
||||
color: "#5858ff",
|
||||
},
|
||||
}));
|
||||
|
||||
interface NotRegisteredContainerProps {
|
||||
|
@ -98,16 +109,17 @@ interface NotRegisteredContainerProps {
|
|||
|
||||
function NotRegisteredContainer(props: NotRegisteredContainerProps) {
|
||||
const { t: translate } = useTranslation();
|
||||
const theme = useTheme();
|
||||
const styles = useStyles();
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<div style={{ marginBottom: theme.spacing(2), flex: "0 0 100%" }}>
|
||||
<Box className={styles.info}>
|
||||
<InformationIcon />
|
||||
</div>
|
||||
<Typography style={{ color: "#5858ff" }}>
|
||||
</Box>
|
||||
<Typography className={styles.infoTypography}>
|
||||
{translate("The resource you're attempting to access requires two-factor authentication")}
|
||||
</Typography>
|
||||
<Typography style={{ color: "#5858ff" }}>
|
||||
<Typography className={styles.infoTypography}>
|
||||
{props.title === "Push Notification"
|
||||
? props.duoSelfEnrollment
|
||||
? translate("Register your first device by clicking on the link below")
|
||||
|
@ -124,10 +136,11 @@ interface MethodContainerProps {
|
|||
}
|
||||
|
||||
function MethodContainer(props: MethodContainerProps) {
|
||||
const theme = useTheme();
|
||||
const styles = useStyles();
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<div style={{ marginBottom: theme.spacing(2) }}>{props.children}</div>
|
||||
<Box className={styles.containerMethod}>{props.children}</Box>
|
||||
<Typography>{props.explanation}</Typography>
|
||||
</Fragment>
|
||||
);
|
||||
|
|
|
@ -1,15 +1,7 @@
|
|||
import React, { ReactNode } from "react";
|
||||
|
||||
import {
|
||||
Dialog,
|
||||
Grid,
|
||||
makeStyles,
|
||||
DialogContent,
|
||||
Button,
|
||||
DialogActions,
|
||||
Typography,
|
||||
useTheme,
|
||||
} from "@material-ui/core";
|
||||
import { Dialog, Grid, DialogContent, Button, DialogActions, Typography, useTheme, Theme } from "@mui/material";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import FingerTouchIcon from "@components/FingerTouchIcon";
|
||||
|
@ -27,7 +19,7 @@ export interface Props {
|
|||
}
|
||||
|
||||
const MethodSelectionDialog = function (props: Props) {
|
||||
const style = useStyles();
|
||||
const styles = useStyles();
|
||||
const theme = useTheme();
|
||||
const { t: translate } = useTranslation();
|
||||
|
||||
|
@ -36,7 +28,7 @@ const MethodSelectionDialog = function (props: Props) {
|
|||
);
|
||||
|
||||
return (
|
||||
<Dialog open={props.open} className={style.root} onClose={props.onClose}>
|
||||
<Dialog open={props.open} className={styles.root} onClose={props.onClose}>
|
||||
<DialogContent>
|
||||
<Grid container justifyContent="center" spacing={1} id="methods-dialog">
|
||||
{props.methods.has(SecondFactorMethod.TOTP) ? (
|
||||
|
@ -76,7 +68,7 @@ const MethodSelectionDialog = function (props: Props) {
|
|||
|
||||
export default MethodSelectionDialog;
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
root: {
|
||||
textAlign: "center",
|
||||
},
|
||||
|
@ -91,7 +83,7 @@ interface MethodItemProps {
|
|||
}
|
||||
|
||||
function MethodItem(props: MethodItemProps) {
|
||||
const style = makeStyles((theme) => ({
|
||||
const style = makeStyles((theme: Theme) => ({
|
||||
item: {
|
||||
paddingTop: theme.spacing(4),
|
||||
paddingBottom: theme.spacing(4),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { Fragment } from "react";
|
||||
|
||||
import { makeStyles } from "@material-ui/core";
|
||||
import { Theme } from "@mui/material";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import classnames from "classnames";
|
||||
import OtpInput from "react-otp-input";
|
||||
|
||||
|
@ -20,11 +21,11 @@ export interface Props {
|
|||
}
|
||||
|
||||
const OTPDial = function (props: Props) {
|
||||
const style = useStyles();
|
||||
const styles = useStyles();
|
||||
|
||||
return (
|
||||
<IconWithContext icon={<Icon state={props.state} period={props.period} />}>
|
||||
<span className={style.otpInput} id="otp-input">
|
||||
<span className={styles.otpInput} id="otp-input">
|
||||
<OtpInput
|
||||
shouldAutoFocus
|
||||
onChange={props.onChange}
|
||||
|
@ -33,7 +34,10 @@ const OTPDial = function (props: Props) {
|
|||
isDisabled={props.state === State.InProgress || props.state === State.Success}
|
||||
isInputNum
|
||||
hasErrored={props.state === State.Failure}
|
||||
inputStyle={classnames(style.otpDigitInput, props.state === State.Failure ? style.inputError : "")}
|
||||
inputStyle={classnames(
|
||||
styles.otpDigitInput,
|
||||
props.state === State.Failure ? styles.inputError : "",
|
||||
)}
|
||||
/>
|
||||
</span>
|
||||
</IconWithContext>
|
||||
|
@ -42,7 +46,7 @@ const OTPDial = function (props: Props) {
|
|||
|
||||
export default OTPDial;
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
timeProgress: {},
|
||||
register: {
|
||||
marginTop: theme.spacing(),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useEffect, useCallback, useRef, useState, ReactNode } from "react";
|
||||
|
||||
import { Button, makeStyles } from "@material-ui/core";
|
||||
import { Button, Theme } from "@mui/material";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
|
||||
import FailureIcon from "@components/FailureIcon";
|
||||
import PushNotificationIcon from "@components/PushNotificationIcon";
|
||||
|
@ -40,7 +41,7 @@ export interface Props {
|
|||
}
|
||||
|
||||
const PushNotificationMethod = function (props: Props) {
|
||||
const style = useStyles();
|
||||
const styles = useStyles();
|
||||
const [state, setState] = useState(State.SignInInProgress);
|
||||
const redirectionURL = useRedirectionURL();
|
||||
const mounted = useIsMountedRef();
|
||||
|
@ -216,7 +217,7 @@ const PushNotificationMethod = function (props: Props) {
|
|||
onSelectClick={fetchDuoDevicesFunc}
|
||||
onRegisterClick={() => window.open(enroll_url, "_blank")}
|
||||
>
|
||||
<div className={style.icon}>{icon}</div>
|
||||
<div className={styles.icon}>{icon}</div>
|
||||
<div className={state !== State.Failure ? "hidden" : ""}>
|
||||
<Button color="secondary" onClick={signInFunc}>
|
||||
Retry
|
||||
|
@ -228,7 +229,7 @@ const PushNotificationMethod = function (props: Props) {
|
|||
|
||||
export default PushNotificationMethod;
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
icon: {
|
||||
width: "64px",
|
||||
height: "64px",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
|
||||
import { Grid, makeStyles, Button } from "@material-ui/core";
|
||||
import { Grid, Button, Theme } from "@mui/material";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Route, Routes, useNavigate } from "react-router-dom";
|
||||
|
||||
|
@ -35,7 +36,7 @@ export interface Props {
|
|||
}
|
||||
|
||||
const SecondFactorForm = function (props: Props) {
|
||||
const style = useStyles();
|
||||
const styles = useStyles();
|
||||
const navigate = useNavigate();
|
||||
const [methodSelectionOpen, setMethodSelectionOpen] = useState(false);
|
||||
const { createInfoNotification, createErrorNotification } = useNotifications();
|
||||
|
@ -106,7 +107,7 @@ const SecondFactorForm = function (props: Props) {
|
|||
</Button>
|
||||
) : null}
|
||||
</Grid>
|
||||
<Grid item xs={12} className={style.methodContainer}>
|
||||
<Grid item xs={12} className={styles.methodContainer}>
|
||||
<Routes>
|
||||
<Route
|
||||
path={SecondFactorTOTPSubRoute}
|
||||
|
@ -159,7 +160,7 @@ const SecondFactorForm = function (props: Props) {
|
|||
|
||||
export default SecondFactorForm;
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
methodContainer: {
|
||||
border: "1px solid #d6d6d6",
|
||||
borderRadius: "10px",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { Fragment, useCallback, useEffect, useRef, useState } from "react";
|
||||
|
||||
import { Button, makeStyles, useTheme } from "@material-ui/core";
|
||||
import { CSSProperties } from "@material-ui/styles";
|
||||
import { Button, Theme, useTheme } from "@mui/material";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
|
||||
import FailureIcon from "@components/FailureIcon";
|
||||
import FingerTouchIcon from "@components/FingerTouchIcon";
|
||||
|
@ -38,7 +38,7 @@ export interface Props {
|
|||
const WebauthnMethod = function (props: Props) {
|
||||
const signInTimeout = 30;
|
||||
const [state, setState] = useState(State.WaitTouch);
|
||||
const style = useStyles();
|
||||
const styles = useStyles();
|
||||
const redirectionURL = useRedirectionURL();
|
||||
const mounted = useIsMountedRef();
|
||||
const [timerPercent, triggerTimer] = useTimer(signInTimeout * 1000 - 500);
|
||||
|
@ -162,7 +162,7 @@ const WebauthnMethod = function (props: Props) {
|
|||
state={methodState}
|
||||
onRegisterClick={props.onRegisterClick}
|
||||
>
|
||||
<div className={style.icon}>
|
||||
<div className={styles.icon}>
|
||||
<Icon state={state} timer={timerPercent} onRetryClick={doInitiateSignIn} />
|
||||
</div>
|
||||
</MethodContainer>
|
||||
|
@ -171,7 +171,7 @@ const WebauthnMethod = function (props: Props) {
|
|||
|
||||
export default WebauthnMethod;
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
icon: {
|
||||
display: "inline-block",
|
||||
},
|
||||
|
@ -188,16 +188,18 @@ function Icon(props: IconProps) {
|
|||
const state = props.state as State;
|
||||
const theme = useTheme();
|
||||
|
||||
const progressBarStyle: CSSProperties = {
|
||||
marginTop: theme.spacing(),
|
||||
};
|
||||
const styles = makeStyles((theme: Theme) => ({
|
||||
progressBar: {
|
||||
marginTop: theme.spacing(),
|
||||
},
|
||||
}))();
|
||||
|
||||
const touch = (
|
||||
<IconWithContext
|
||||
icon={<FingerTouchIcon size={64} animated strong />}
|
||||
className={state === State.WaitTouch ? undefined : "hidden"}
|
||||
>
|
||||
<LinearProgressBar value={props.timer} style={progressBarStyle} height={theme.spacing(2)} />
|
||||
<LinearProgressBar value={props.timer} className={styles.progressBar} height={theme.spacing(2)} />
|
||||
</IconWithContext>
|
||||
);
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useEffect, useCallback, useState } from "react";
|
||||
|
||||
import { Typography, makeStyles } from "@material-ui/core";
|
||||
import { Theme, Typography } from "@mui/material";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Navigate } from "react-router-dom";
|
||||
|
||||
|
@ -16,7 +17,7 @@ export interface Props {}
|
|||
|
||||
const SignOut = function (props: Props) {
|
||||
const mounted = useIsMountedRef();
|
||||
const style = useStyles();
|
||||
const styles = useStyles();
|
||||
const { createErrorNotification } = useNotifications();
|
||||
const redirectionURL = useRedirectionURL();
|
||||
const redirector = useRedirector();
|
||||
|
@ -56,14 +57,14 @@ const SignOut = function (props: Props) {
|
|||
|
||||
return (
|
||||
<LoginLayout title={translate("Sign out")}>
|
||||
<Typography className={style.typo}>{translate("You're being signed out and redirected")}...</Typography>
|
||||
<Typography className={styles.typo}>{translate("You're being signed out and redirected")}...</Typography>
|
||||
</LoginLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default SignOut;
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
typo: {
|
||||
padding: theme.spacing(),
|
||||
},
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useState } from "react";
|
||||
|
||||
import { Grid, Button, makeStyles } from "@material-ui/core";
|
||||
import { Grid, Button, Theme } from "@mui/material";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
|
@ -11,7 +12,7 @@ import LoginLayout from "@layouts/LoginLayout";
|
|||
import { initiateResetPasswordProcess } from "@services/ResetPassword";
|
||||
|
||||
const ResetPasswordStep1 = function () {
|
||||
const style = useStyles();
|
||||
const styles = useStyles();
|
||||
const [username, setUsername] = useState("");
|
||||
const [error, setError] = useState(false);
|
||||
const { createInfoNotification, createErrorNotification } = useNotifications();
|
||||
|
@ -42,7 +43,7 @@ const ResetPasswordStep1 = function () {
|
|||
|
||||
return (
|
||||
<LoginLayout title={translate("Reset password")} id="reset-password-step1-stage">
|
||||
<Grid container className={style.root} spacing={2}>
|
||||
<Grid container className={styles.root} spacing={2}>
|
||||
<Grid item xs={12}>
|
||||
<FixedTextField
|
||||
id="username-textfield"
|
||||
|
@ -83,7 +84,7 @@ const ResetPasswordStep1 = function () {
|
|||
|
||||
export default ResetPasswordStep1;
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
root: {
|
||||
marginTop: theme.spacing(2),
|
||||
marginBottom: theme.spacing(2),
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import React, { useCallback, useEffect, useState } from "react";
|
||||
|
||||
import { Button, Grid, IconButton, InputAdornment, makeStyles } from "@material-ui/core";
|
||||
import { Visibility, VisibilityOff } from "@material-ui/icons";
|
||||
import { Visibility, VisibilityOff } from "@mui/icons-material";
|
||||
import { Button, Grid, IconButton, InputAdornment, Theme } from "@mui/material";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import classnames from "classnames";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
|
@ -17,7 +18,7 @@ import { completeResetPasswordProcess, resetPassword } from "@services/ResetPass
|
|||
import { extractIdentityToken } from "@utils/IdentityToken";
|
||||
|
||||
const ResetPasswordStep2 = function () {
|
||||
const style = useStyles();
|
||||
const styles = useStyles();
|
||||
const location = useLocation();
|
||||
const [formDisabled, setFormDisabled] = useState(true);
|
||||
const [password1, setPassword1] = useState("");
|
||||
|
@ -110,7 +111,7 @@ const ResetPasswordStep2 = function () {
|
|||
|
||||
return (
|
||||
<LoginLayout title={translate("Enter new password")} id="reset-password-step2-stage">
|
||||
<Grid container className={style.root} spacing={2}>
|
||||
<Grid container className={styles.root} spacing={2}>
|
||||
<Grid item xs={12}>
|
||||
<FixedTextField
|
||||
id="password1-textfield"
|
||||
|
@ -121,7 +122,7 @@ const ResetPasswordStep2 = function () {
|
|||
disabled={formDisabled}
|
||||
onChange={(e) => setPassword1(e.target.value)}
|
||||
error={errorPassword1}
|
||||
className={classnames(style.fullWidth)}
|
||||
className={classnames(styles.fullWidth)}
|
||||
autoComplete="new-password"
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
|
@ -130,6 +131,7 @@ const ResetPasswordStep2 = function () {
|
|||
aria-label="toggle password visibility"
|
||||
onClick={(e) => setShowPassword(!showPassword)}
|
||||
edge="end"
|
||||
size="large"
|
||||
>
|
||||
{showPassword ? <VisibilityOff></VisibilityOff> : <Visibility></Visibility>}
|
||||
</IconButton>
|
||||
|
@ -157,7 +159,7 @@ const ResetPasswordStep2 = function () {
|
|||
ev.preventDefault();
|
||||
}
|
||||
}}
|
||||
className={classnames(style.fullWidth)}
|
||||
className={classnames(styles.fullWidth)}
|
||||
autoComplete="new-password"
|
||||
/>
|
||||
</Grid>
|
||||
|
@ -169,7 +171,7 @@ const ResetPasswordStep2 = function () {
|
|||
name="password1"
|
||||
disabled={formDisabled}
|
||||
onClick={handleResetClick}
|
||||
className={style.fullWidth}
|
||||
className={styles.fullWidth}
|
||||
>
|
||||
{translate("Reset")}
|
||||
</Button>
|
||||
|
@ -181,7 +183,7 @@ const ResetPasswordStep2 = function () {
|
|||
color="primary"
|
||||
name="password2"
|
||||
onClick={handleCancelClick}
|
||||
className={style.fullWidth}
|
||||
className={styles.fullWidth}
|
||||
>
|
||||
{translate("Cancel")}
|
||||
</Button>
|
||||
|
@ -193,7 +195,7 @@ const ResetPasswordStep2 = function () {
|
|||
|
||||
export default ResetPasswordStep2;
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
root: {
|
||||
marginTop: theme.spacing(2),
|
||||
marginBottom: theme.spacing(2),
|
||||
|
|
Loading…
Reference in New Issue