Add base web UI

This commit is contained in:
2025-03-18 19:14:46 +01:00
parent abc75786f7
commit dbe1ec22e0
36 changed files with 2575 additions and 248 deletions

View File

@@ -0,0 +1,3 @@
export function HomeRoute(): React.ReactElement {
return <>home authenticated todo</>;
}

View File

@@ -0,0 +1,23 @@
import { Button } from "@mui/material";
import { RouterLink } from "../widgets/RouterLink";
export function NotFoundRoute(): React.ReactElement {
return (
<div
style={{
textAlign: "center",
flex: "1",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
}}
>
<h1>404 Not found</h1>
<p>The page you requested was not found!</p>
<RouterLink to="/">
<Button>Go back home</Button>
</RouterLink>
</div>
);
}

View File

@@ -0,0 +1,51 @@
import { Alert, CircularProgress } from "@mui/material";
import Button from "@mui/material/Button";
import * as React from "react";
import { AuthApi } from "../../api/AuthApi";
import { ServerApi } from "../../api/ServerApi";
/**
* Login form
*/
export function LoginRoute(): React.ReactElement {
const [loading, setLoading] = React.useState(false);
const [error, setError] = React.useState<string | null>(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 (
<>
<CircularProgress />
</>
);
return (
<>
{error && (
<Alert style={{ width: "100%" }} severity="error">
{error}
</Alert>
)}
<div>
<Button
style={{ textAlign: "center", width: "100%", marginTop: "20px" }}
onClick={() => authWithOpenID()}
>
Authenticate using {ServerApi.Config.oidc_provider_name}
</Button>
</div>
</>
);
}

View File

@@ -0,0 +1,53 @@
import { CircularProgress } from "@mui/material";
import { useEffect, useRef, useState } from "react";
import { useNavigate, useSearchParams } from "react-router-dom";
import { AuthApi } from "../../api/AuthApi";
import { useAuth } from "../../App";
import { AuthSingleMessage } from "../../widgets/AuthSingleMessage";
/**
* OpenID login callback route
*/
export function OIDCCbRoute(): React.ReactElement {
const auth = useAuth();
const navigate = useNavigate();
const [error, setError] = useState(false);
const [searchParams] = useSearchParams();
const code = searchParams.get("code");
const state = searchParams.get("state");
const count = useRef("");
useEffect(() => {
const load = async () => {
try {
if (count.current === code) {
return;
}
count.current = code!;
await AuthApi.FinishOpenIDLogin(code!, state!);
navigate("/");
auth.setSignedIn(true);
} catch (e) {
console.error(e);
setError(true);
}
};
load();
});
if (error)
return (
<AuthSingleMessage message="Failed to finalize OpenID authentication!" />
);
return (
<>
<CircularProgress />
</>
);
}