diff --git a/matrixgw_frontend/index.html b/matrixgw_frontend/index.html
index 03c4e8f..5d7e649 100644
--- a/matrixgw_frontend/index.html
+++ b/matrixgw_frontend/index.html
@@ -2,9 +2,9 @@
-
+
- matrixgw_frontend
+ MatrixGW
diff --git a/matrixgw_frontend/package-lock.json b/matrixgw_frontend/package-lock.json
index e80d450..152f32f 100644
--- a/matrixgw_frontend/package-lock.json
+++ b/matrixgw_frontend/package-lock.json
@@ -11,6 +11,8 @@
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@fontsource/roboto": "^5.2.8",
+ "@mdi/js": "^7.4.47",
+ "@mdi/react": "^1.6.1",
"@mui/icons-material": "^7.3.5",
"@mui/material": "^7.3.5",
"react": "^19.1.1",
@@ -789,6 +791,21 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@mdi/js": {
+ "version": "7.4.47",
+ "resolved": "https://registry.npmjs.org/@mdi/js/-/js-7.4.47.tgz",
+ "integrity": "sha512-KPnNOtm5i2pMabqZxpUz7iQf+mfrYZyKCZ8QNz85czgEt7cuHcGorWfdzUMWYA0SD+a6Hn4FmJ+YhzzzjkTZrQ==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@mdi/react": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/@mdi/react/-/react-1.6.1.tgz",
+ "integrity": "sha512-4qZeDcluDFGFTWkHs86VOlHkm6gnKaMql13/gpIcUQ8kzxHgpj31NuCkD8abECVfbULJ3shc7Yt4HJ6Wu6SN4w==",
+ "license": "MIT",
+ "dependencies": {
+ "prop-types": "^15.7.2"
+ }
+ },
"node_modules/@mui/core-downloads-tracker": {
"version": "7.3.5",
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.3.5.tgz",
diff --git a/matrixgw_frontend/package.json b/matrixgw_frontend/package.json
index 3207e3c..823193f 100644
--- a/matrixgw_frontend/package.json
+++ b/matrixgw_frontend/package.json
@@ -13,6 +13,8 @@
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@fontsource/roboto": "^5.2.8",
+ "@mdi/js": "^7.4.47",
+ "@mdi/react": "^1.6.1",
"@mui/icons-material": "^7.3.5",
"@mui/material": "^7.3.5",
"react": "^19.1.1",
diff --git a/matrixgw_frontend/src/routes/auth/LoginRoute.tsx b/matrixgw_frontend/src/routes/auth/LoginRoute.tsx
index 6190120..75b9457 100644
--- a/matrixgw_frontend/src/routes/auth/LoginRoute.tsx
+++ b/matrixgw_frontend/src/routes/auth/LoginRoute.tsx
@@ -1,3 +1,50 @@
+import { Alert, Box, Button, CircularProgress } from "@mui/material";
+import Icon from "@mdi/react";
+import { mdiOpenid } from "@mdi/js";
+import { ServerApi } from "../../api/ServerApi";
+import React from "react";
+import { AuthApi } from "../../api/AuthApi";
+
export function LoginRoute(): React.ReactElement {
- return <>LoginRoute>;
+ const [loading, setLoading] = React.useState(false);
+ const [error, setError] = React.useState(null);
+
+ const authWithOpenID = async () => {
+ try {
+ setLoading(true);
+
+ const res = await AuthApi.StartOpenIDLogin();
+ window.location.href = res.url;
+ } catch (e) {
+ console.error(e);
+ setError("Failed to initialize OpenID login");
+ }
+ };
+
+ if (loading)
+ return (
+
+
+
+ );
+
+ return (
+ <>
+ {error && (
+
+ {error}
+
+ )}
+
+ }
+ >
+ Sign in with {ServerApi.Config.oidc_provider_name}
+
+
+ >
+ );
}
diff --git a/matrixgw_frontend/src/routes/auth/OIDCCbRoute.tsx b/matrixgw_frontend/src/routes/auth/OIDCCbRoute.tsx
index 90c67f8..82f80fe 100644
--- a/matrixgw_frontend/src/routes/auth/OIDCCbRoute.tsx
+++ b/matrixgw_frontend/src/routes/auth/OIDCCbRoute.tsx
@@ -46,8 +46,8 @@ export function OIDCCbRoute(): React.ReactElement {
);
return (
- <>
+
- >
+
);
}
diff --git a/matrixgw_frontend/src/widgets/auth/BaseLoginPage.tsx b/matrixgw_frontend/src/widgets/auth/BaseLoginPage.tsx
index 866dd64..a6d86da 100644
--- a/matrixgw_frontend/src/widgets/auth/BaseLoginPage.tsx
+++ b/matrixgw_frontend/src/widgets/auth/BaseLoginPage.tsx
@@ -1,3 +1,71 @@
+import { mdiMessageTextFast } from "@mdi/js";
+import Icon from "@mdi/react";
+import { Typography } from "@mui/material";
+import MuiCard from "@mui/material/Card";
+import Stack from "@mui/material/Stack";
+import { styled } from "@mui/material/styles";
+import { Outlet } from "react-router";
+
+const Card = styled(MuiCard)(({ theme }) => ({
+ display: "flex",
+ flexDirection: "column",
+ alignSelf: "center",
+ width: "100%",
+ padding: theme.spacing(4),
+ gap: theme.spacing(2),
+ margin: "auto",
+ [theme.breakpoints.up("sm")]: {
+ maxWidth: "450px",
+ },
+ boxShadow:
+ "hsla(220, 30%, 5%, 0.05) 0px 5px 15px 0px, hsla(220, 25%, 10%, 0.05) 0px 15px 35px -5px",
+ ...theme.applyStyles("dark", {
+ boxShadow:
+ "hsla(220, 30%, 5%, 0.5) 0px 5px 15px 0px, hsla(220, 25%, 10%, 0.08) 0px 15px 35px -5px",
+ }),
+}));
+
+const SignInContainer = styled(Stack)(({ theme }) => ({
+ height: "calc((1 - var(--template-frame-height, 0)) * 100dvh)",
+ minHeight: "100%",
+ padding: theme.spacing(2),
+ [theme.breakpoints.up("sm")]: {
+ padding: theme.spacing(4),
+ },
+ "&::before": {
+ content: '""',
+ display: "block",
+ position: "absolute",
+ zIndex: -1,
+ inset: 0,
+ backgroundImage:
+ "radial-gradient(ellipse at 50% 50%, hsl(210, 100%, 97%), hsl(0, 0%, 100%))",
+ backgroundRepeat: "no-repeat",
+ ...theme.applyStyles("dark", {
+ backgroundImage:
+ "radial-gradient(at 50% 50%, hsla(210, 100%, 16%, 0.5), hsl(220, 30%, 5%))",
+ }),
+ },
+}));
+
export function BaseLoginPage(): React.ReactElement {
- return Todo login page route
;
+ return (
+
+
+
+ {" "}
+ MatrixGW
+
+
+
+
+ );
}