Skip to content
This repository was archived by the owner on Feb 10, 2025. It is now read-only.

Commit 229d4e2

Browse files
committed
Merge branch 'main' into TILA-1201
* main: TILA-1519 a11y fixes TILA-1566 disable sentry distibuted tracing add sorting to selects where it makes sense (#298) TILA-1515 (#294) remove explicit timeout due to api slowness
2 parents c8028ab + ce77970 commit 229d4e2

40 files changed

Lines changed: 652 additions & 269 deletions

admin-ui/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
},
4545
"dependencies": {
4646
"@apollo/client": "^3.4.13",
47-
"@axa-fr/react-oidc-context": "^3.1.6",
47+
"@axa-fr/react-oidc-context": "3.1.6",
4848
"@n8tb1t/use-scroll-position": "^2.0.3",
4949
"@react-pdf/renderer": "2.0.15",
5050
"@sentry/react": "^6.18.1",
@@ -68,6 +68,7 @@
6868
"query-string": "^7.0.0",
6969
"react": "^17.0.2",
7070
"react-dom": "^17.0.2",
71+
"react-error-boundary": "^3.1.4",
7172
"react-i18next": "^11.8.5",
7273
"react-map-gl": "5.3.16",
7374
"react-quill": "beta",
@@ -111,5 +112,4 @@
111112
"testcafe": "^1.11.0",
112113
"typescript": "^4.3.4"
113114
}
114-
115115
}

admin-ui/public/5xx.png

62.7 KB
Loading

admin-ui/src/App.tsx

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import React from "react";
22
import { BrowserRouter, Route, Switch } from "react-router-dom";
3-
import { useReactOidc } from "@axa-fr/react-oidc-context";
43
import ApplicationRound from "./component/recurring-reservations/ApplicationRound";
54
import PageWrapper from "./component/PageWrapper";
65
import "./i18n";
@@ -10,7 +9,6 @@ import Recommendation from "./component/recurring-reservations/Recommendation";
109
import RecommendationsByApplicant from "./component/recurring-reservations/RecommendationsByApplicant";
1110
import ApplicationRounds from "./component/recurring-reservations/ApplicationRounds";
1211
import AllApplicationRounds from "./component/recurring-reservations/AllApplicationRounds";
13-
import MainLander from "./component/MainLander";
1412
import Approval from "./component/decisions/Approval";
1513
import Applications from "./component/applications/Applications";
1614
import Criteria from "./component/recurring-reservations/Criteria";
@@ -38,22 +36,14 @@ import RequestedReservations from "./component/reservations/requested/RequestedR
3836
import RequestedReservation from "./component/reservations/requested/RequestedReservation";
3937
import PrivateRoutes from "./common/PrivateRoutes";
4038
import { prefixes } from "./common/urls";
41-
import Error403 from "./common/Error403";
4239

4340
function App(): JSX.Element {
44-
const { oidcUser } = useReactOidc();
45-
4641
return (
4742
<BrowserRouter basename={publicUrl}>
4843
<PageWrapper>
4944
<Switch>
50-
<Route
51-
exact
52-
path="/"
53-
component={oidcUser ? ApplicationRounds : MainLander}
54-
/>
55-
<Route exact path="/403" component={Error403} />
5645
<PrivateRoutes>
46+
<Route exact path="/" component={ApplicationRounds} />
5747
<Route
5848
exact
5949
path={`${prefixes.applications}/:applicationId`}

admin-ui/src/common/Error403.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import { useReactOidc } from "@axa-fr/react-oidc-context";
21
import { Button, Link } from "hds-react";
32
import React from "react";
43
import styled from "styled-components";
4+
import { useAuthState } from "../context/AuthStateContext";
55
import { H1 } from "../styles/new-typography";
66
import { breakpoints } from "../styles/util";
77
import { localLogout } from "./auth/util";
8+
import { publicUrl } from "./const";
89

910
const Wrapper = styled.div`
1011
margin: 0 var(--spacing-s);
@@ -48,7 +49,7 @@ const ButtonContainer = styled.div`
4849
`;
4950

5051
const Error403 = (): JSX.Element => {
51-
const { oidcUser, logout } = useReactOidc();
52+
const { authState } = useAuthState();
5253

5354
return (
5455
<Wrapper>
@@ -70,20 +71,19 @@ const Error403 = (): JSX.Element => {
7071
>
7172
Anna palautetta
7273
</Link>
73-
{oidcUser && (
74+
{authState.state !== "NotAutenticated" && (
7475
<ButtonContainer>
7576
<Button
7677
onClick={() => {
7778
localLogout();
78-
logout();
7979
}}
8080
>
8181
Kirjaudu ulos
8282
</Button>
8383
</ButtonContainer>
8484
)}
8585
</Content>
86-
<Image src="/403.png" />
86+
<Image src={`${publicUrl}/403.png`} />
8787
</Wrapper>
8888
);
8989
};

admin-ui/src/common/Error5xx.tsx

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { Link } from "hds-react";
2+
import React from "react";
3+
import styled from "styled-components";
4+
import { H1 } from "../styles/new-typography";
5+
import { breakpoints } from "../styles/util";
6+
import { publicUrl } from "./const";
7+
8+
const Wrapper = styled.div`
9+
margin: 0 var(--spacing-s);
10+
word-break: break-word;
11+
gap: var(--spacing-layout-m);
12+
display: flex;
13+
flex-direction: column;
14+
h1 {
15+
margin-bottom: 0;
16+
font-size: 2.5em;
17+
}
18+
19+
@media (min-width: ${breakpoints.l}) {
20+
margin: var(--spacing-layout-2-xl);
21+
grid-template-columns: 3fr 1fr;
22+
display: grid;
23+
h1 {
24+
font-size: 4em;
25+
}
26+
}
27+
`;
28+
29+
const Content = styled.div`
30+
display: flex;
31+
flex-direction: column;
32+
margin-left: auto;
33+
margin-right: auto;
34+
gap: 1.5rem;
35+
`;
36+
37+
const Image = styled.img`
38+
width: 100%;
39+
max-width: 400px;
40+
@media (min-width: ${breakpoints.l}) {
41+
width: auto;
42+
}
43+
`;
44+
45+
const Error5xx = (): JSX.Element => {
46+
return (
47+
<Wrapper>
48+
<Content>
49+
<H1>Jokin meni vikaan</H1>
50+
<p>
51+
Pahoittelut, emme valitettavasti pysty näyttämään sivua juuri nyt.
52+
Yritä myöhemmin uudelleen!
53+
</p>
54+
<Link external href="/">
55+
Siirry Varaamon etusivulle
56+
</Link>
57+
<Link
58+
external
59+
href="https://app.helmet-kirjasto.fi/forms/?site=varaamopalaute&ref=https://tilavaraus.hel.fi/"
60+
>
61+
Anna palautetta
62+
</Link>
63+
</Content>
64+
<Image src={`${publicUrl}/5xx.png`} />
65+
</Wrapper>
66+
);
67+
};
68+
69+
export default Error5xx;
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// eslint-disable-next-line import/no-unresolved
2+
import { Button, IconArrowRight, IconGroup } from "hds-react";
3+
import React, { useState } from "react";
4+
import { useTranslation } from "react-i18next";
5+
import styled from "styled-components";
6+
import Footer from "../component/Footer";
7+
import KorosHeading, { Heading } from "../component/KorosHeading";
8+
import { useAuthState } from "../context/AuthStateContext";
9+
import HeroImage from "../images/hero-user@1x.jpg";
10+
import { H2 } from "../styles/typography";
11+
import { breakpoints } from "../styles/util";
12+
13+
const Wrapper = styled.div``;
14+
15+
const LoginBtn = styled(Button).attrs({
16+
iconLeft: <IconGroup className="icon-group" />,
17+
iconRight: <IconArrowRight className="icon-arrow" />,
18+
style: {
19+
"--color-bus": "var(--color-white)",
20+
"--color": "var(--color-black)",
21+
"--background-color-focus": "var(--color-bus)",
22+
"--color-focus": "var(--color-black)",
23+
} as React.CSSProperties,
24+
})`
25+
font-family: var(--tilavaraus-admin-font-bold);
26+
font-size: var(--fontsize-heading-l);
27+
font-weight: 700;
28+
margin-top: var(--spacing-m);
29+
padding: var(--spacing-xs) var(--spacing-m) var(--spacing-xs) var(--spacing-l);
30+
transform: scale(0.5);
31+
32+
svg {
33+
display: flex;
34+
}
35+
36+
span {
37+
margin: 0 0 0 var(--spacing-s);
38+
}
39+
40+
.icon-group {
41+
transform: scale(1.5);
42+
}
43+
44+
@media (min-width: ${breakpoints.m}) {
45+
transform: scale(1);
46+
}
47+
`;
48+
49+
const Content = styled.div`
50+
max-width: 44rem;
51+
min-height: 30rem;
52+
margin: var(--spacing-3-xl) auto var(--spacing-2-xl);
53+
padding: 0 var(--spacing-xl);
54+
55+
@media (min-width: ${breakpoints.m}) {
56+
text-align: center;
57+
}
58+
`;
59+
60+
const Ingress = styled(H2)`
61+
line-height: 1.8125rem;
62+
`;
63+
64+
function ErrorNotLoggedIn(): JSX.Element {
65+
const { t } = useTranslation();
66+
const { authState } = useAuthState();
67+
const [loading, setLoading] = useState(false);
68+
69+
return (
70+
<Wrapper>
71+
<KorosHeading heroImage={HeroImage}>
72+
<Heading>{t("common.applicationName")}</Heading>
73+
<LoginBtn
74+
isLoading={loading}
75+
onClick={() => {
76+
setLoading(true);
77+
const { login } = authState;
78+
if (login) {
79+
login();
80+
}
81+
}}
82+
>
83+
{t("Navigation.login")}
84+
</LoginBtn>
85+
</KorosHeading>
86+
<Content>
87+
<Ingress>{t("MainLander.ingress")}</Ingress>
88+
</Content>
89+
<Footer />
90+
</Wrapper>
91+
);
92+
}
93+
94+
export default ErrorNotLoggedIn;
Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,34 @@
1-
import { OidcSecure } from "@axa-fr/react-oidc-context";
21
import React from "react";
2+
import { useTranslation } from "react-i18next";
3+
import { useAuthState } from "../context/AuthStateContext";
34

4-
import { useData } from "../context/DataContext";
55
import Error403 from "./Error403";
6+
import Error5xx from "./Error5xx";
7+
import ErrorNotLoggedIn from "./ErrorNotAuthenticated";
68

79
type Props = {
810
children: React.ReactChild[] | React.ReactChild;
911
};
1012

1113
const PrivateRoutes = ({ children }: Props): JSX.Element => {
12-
const { hasAnyPermissions } = useData();
14+
const { authState } = useAuthState();
15+
const { t } = useTranslation();
1316

14-
if (hasAnyPermissions()) {
15-
return <OidcSecure>{children}</OidcSecure>;
17+
switch (authState.state) {
18+
case "HasPermissions":
19+
return <>{children}</>;
20+
case "Error":
21+
return <Error5xx />;
22+
case "NoPermissions":
23+
return <Error403 />;
24+
case "NotAutenticated":
25+
return <ErrorNotLoggedIn />;
26+
case "Unknown":
27+
case "Authenticated":
28+
return <span>{t("AuthState.initializing")}</span>;
29+
default:
30+
throw new Error(`Illegal auth state :'${authState.state}'`);
1631
}
17-
18-
return <Error403 />;
1932
};
2033

2134
export default PrivateRoutes;

admin-ui/src/common/apolloClient.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,11 @@ import { setContext } from "@apollo/client/link/context";
99
import { onError } from "@apollo/client/link/error";
1010
import { set } from "lodash";
1111

12-
import {
13-
getAccessToken,
14-
getApiAccessToken,
15-
updateApiAccessToken,
16-
} from "./auth/util";
12+
import { getApiAccessToken, updateApiAccessToken } from "./auth/util";
1713
import { apiBaseUrl } from "./const";
1814
import { CustomFormData } from "./CustomFormData";
1915

20-
const getNewToken = (): Promise<string> =>
21-
updateApiAccessToken(getAccessToken());
16+
const getNewToken = () => updateApiAccessToken();
2217

2318
const uploadLinkOptions = {
2419
uri: `${apiBaseUrl}/graphql/`,

admin-ui/src/common/auth/CustomUserStore.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import { oidcClientId, oidcUrl, apiScope } from "../const";
1+
import { oidcClientId, oidcUrl } from "../const";
22

33
export default class CustomUserStore {
44
storage = window.localStorage;
55

66
setItem(key: string, value: string): void {
77
this.storage.setItem(key, value);
8-
this.storage.removeItem(`oidc.apiToken.${apiScope}`); // side effect, make sure api access token is cleared
98
}
109

1110
getItem(key: string): string | null {

0 commit comments

Comments
 (0)