Skip to content

Commit

Permalink
Fix reloading (#301)
Browse files Browse the repository at this point in the history
  • Loading branch information
tschumpr authored Sep 13, 2024
2 parents 7d76dc1 + 80dadb6 commit 291d783
Show file tree
Hide file tree
Showing 15 changed files with 113 additions and 85 deletions.
4 changes: 4 additions & 0 deletions src/Geopilot.Api/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@
app.UseDefaultFiles();
app.UseStaticFiles();

app.UseRouting();

if (app.Environment.IsDevelopment())
{
app.UseCors("All");
Expand Down Expand Up @@ -264,4 +266,6 @@

app.MapReverseProxy();

app.MapFallbackToFile("index.html");

app.Run();
18 changes: 13 additions & 5 deletions src/Geopilot.Frontend/cypress/e2e/app.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ describe("General app tests", () => {
it("shows no login button if auth settings could not be loaded", () => {
loadWithoutAuth();
cy.get('[data-cy="login-button"]').should("not.exist");
cy.get('[data-cy="delivery"]').should("exist");
});

it.skip("registers new users and logs them in", () => {
Expand Down Expand Up @@ -52,23 +53,30 @@ describe("General app tests", () => {
selectAdminNavItem("mandates");
selectAdminNavItem("organisations");
selectAdminNavItem("delivery-overview");
cy.reload();
isSelectedNavItem("admin-delivery-overview-nav", "admin-navigation");
cy.location().should(location => {
expect(location.pathname).to.eq("/admin/delivery-overview");
});
});

it("updates the language when the user selects a different language", () => {
cy.visit("/");
loginAsAdmin();
openTool("admin");

cy.contains("EN");
cy.contains("Log In");
cy.contains("Rows per page");

selectLanguage("de");
cy.contains("DE");
cy.contains("Anmelden");
cy.contains("Zeilen pro Seite");

selectLanguage("fr");
cy.contains("FR");
cy.contains("Se connecter");
cy.contains("Lignes par page");

selectLanguage("it");
cy.contains("IT");
cy.contains("Accedi");
cy.contains("Righe per pagina");
});
});
9 changes: 6 additions & 3 deletions src/Geopilot.Frontend/cypress/e2e/helpers/appHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,12 @@ export const createBaseSelector = parent => {
* Opens the tool navigation. Requires the user to be logged in.
*/
export const openToolMenu = () => {
if (!cy.get('[data-cy="tool-navigation"]').should("be.visible")) {
cy.get('[data-cy="loggedInUser-button"]').click();
}
cy.get("body").then($body => {
const elementExists = $body.find('[data-cy="tool-navigation"]').length > 0;
if (!elementExists) {
cy.get('[data-cy="loggedInUser-button"]').click();
}
});
};

/**
Expand Down
63 changes: 34 additions & 29 deletions src/Geopilot.Frontend/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ import { PrivacyPolicy } from "./pages/footer/privacyPolicy.tsx";
import { About } from "./pages/footer/about.tsx";
import { Imprint } from "./pages/footer/imprint.tsx";
import { DeliveryProvider } from "./pages/delivery/deliveryContext.tsx";
import { CircularProgress } from "@mui/material";

export const App: FC = () => {
const [isSubMenuOpen, setIsSubMenuOpen] = useState(false);
const { isAdmin } = useGeopilotAuth();
const { isLoading, isAdmin } = useGeopilotAuth();

return (
<AppBox>
Expand All @@ -30,34 +31,38 @@ export const App: FC = () => {
/>
<LayoutBox>
<PageContentBox>
<Routes>
<Route
path="/"
element={
<DeliveryProvider>
<Delivery />
</DeliveryProvider>
}
/>
{isAdmin ? (
<>
<Route path="admin" element={<Navigate to="/admin/delivery-overview" replace />} />
<Route
path="admin"
element={<Admin isSubMenuOpen={isSubMenuOpen} setIsSubMenuOpen={setIsSubMenuOpen} />}>
<Route path="delivery-overview" element={<DeliveryOverview />} />
<Route path="users" element={<Users />} />
<Route path="mandates" element={<Mandates />} />
<Route path="organisations" element={<Organisations />} />
</Route>
</>
) : (
<Route path="admin/*" element={<Navigate to="/" replace />} />
)}
<Route path="/imprint" element={<Imprint />} />
<Route path="/privacy-policy" element={<PrivacyPolicy />} />
<Route path="/about" element={<About />} />
</Routes>
{isLoading ? (
<CircularProgress />
) : (
<Routes>
<Route
path="/"
element={
<DeliveryProvider>
<Delivery />
</DeliveryProvider>
}
/>
{isAdmin ? (
<>
<Route path="admin" element={<Navigate to="/admin/delivery-overview" replace />} />
<Route
path="admin"
element={<Admin isSubMenuOpen={isSubMenuOpen} setIsSubMenuOpen={setIsSubMenuOpen} />}>
<Route path="delivery-overview" element={<DeliveryOverview />} />
<Route path="users" element={<Users />} />
<Route path="mandates" element={<Mandates />} />
<Route path="organisations" element={<Organisations />} />
</Route>
</>
) : (
<Route path="admin/*" element={<Navigate to="/" replace />} />
)}
<Route path="/imprint" element={<Imprint />} />
<Route path="/privacy-policy" element={<PrivacyPolicy />} />
<Route path="/about" element={<About />} />
</Routes>
)}
</PageContentBox>
<Footer />
</LayoutBox>
Expand Down
5 changes: 3 additions & 2 deletions src/Geopilot.Frontend/src/auth/authInterfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { PropsWithChildren } from "react";
import { User } from "../api/apiInterfaces.ts";

export interface GeopilotAuthContextInterface {
enabled: boolean;
user: User | undefined;
authEnabled: boolean;
isLoading: boolean;
user: User | null | undefined;
isAdmin: boolean;
login: () => void;
logout: () => void;
Expand Down
15 changes: 10 additions & 5 deletions src/Geopilot.Frontend/src/auth/geopilotAuthComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { ApiAuthConfigurationProvider } from "./apiAuthConfigurationContext";
import { GeopilotAuthContextInterface } from "./authInterfaces";
import { OidcContainerProvider } from "./oidcContainerContext";
import { UserProvider } from "./userContext";
import { useUser } from ".";
import { useApiAuthConfiguration, useUser } from ".";
import { useAuth } from "react-oidc-context";
import { CookieSynchronizer } from "./cookieSynchronizer";

export const GeopilotAuthContext = createContext<GeopilotAuthContextInterface>({
enabled: false,
authEnabled: false,
isLoading: false,
user: undefined,
isAdmin: false,
login: () => {
Expand All @@ -35,8 +36,11 @@ export const GeopilotAuthProvider: FC<PropsWithChildren> = ({ children }) => {
const GeopilotAuthContextMerger: FC<PropsWithChildren> = ({ children }) => {
const auth = useAuth();
const user = useUser();
const apiSetting = useApiAuthConfiguration();

const authEnabled = !!(apiSetting && apiSetting.clientId && apiSetting.authority);
const isLoading = !((!!apiSetting && !authEnabled) || user !== undefined);

const enabled = auth !== undefined && !auth.isLoading;
const getLoginFunction = () => {
if (!auth) return () => {};
if (window.Cypress) {
Expand All @@ -49,9 +53,10 @@ const GeopilotAuthContextMerger: FC<PropsWithChildren> = ({ children }) => {
return (
<GeopilotAuthContext.Provider
value={{
enabled: enabled,
authEnabled: authEnabled,
isLoading: isLoading,
user: user,
isAdmin: enabled && !!user?.isAdmin,
isAdmin: !!user?.isAdmin,
login: getLoginFunction(),
logout: auth !== undefined ? auth.signoutRedirect : () => {},
}}>
Expand Down
10 changes: 5 additions & 5 deletions src/Geopilot.Frontend/src/auth/userContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { User } from "../api/apiInterfaces";
import { useAuth } from "react-oidc-context";
import { useApi } from "../api";

export const UserContext = createContext<User | undefined>(undefined);
export const UserContext = createContext<User | null | undefined>(undefined);

export const UserProvider: FC<PropsWithChildren> = ({ children }) => {
const [user, setUser] = useState<User>();
const [user, setUser] = useState<User | null>();
const auth = useAuth();
const { fetchApi } = useApi();

Expand All @@ -22,10 +22,10 @@ export const UserProvider: FC<PropsWithChildren> = ({ children }) => {
useEffect(() => {
if (auth?.isAuthenticated) {
fetchUserInfo();
} else if (!auth?.isLoading) {
setUser(undefined);
} else if (!!auth && !auth?.isLoading) {
setUser(null);
}
}, [auth?.isAuthenticated, auth?.isLoading, fetchUserInfo]);
}, [auth, auth?.isAuthenticated, auth?.isLoading, fetchUserInfo]);

return <UserContext.Provider value={user}>{children}</UserContext.Provider>;
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,41 @@ export const AppSettingsProvider: FC<PropsWithChildren> = ({ children }) => {
const [termsOfUse, setTermsOfUse] = useState<string | null>();

useEffect(() => {
fetchApi<ClientSettings>("client-settings.json")
fetchApi<ClientSettings>("/client-settings.json", { responseType: ContentType.Json })
.then(setClientSettings)
.catch(() => setClientSettings(null));
fetchApi<string>("terms-of-use.md", { responseType: ContentType.Markdown })
fetchApi<string>("/terms-of-use.md", { responseType: ContentType.Markdown })
.then(setTermsOfUse)
.catch(() => setTermsOfUse(null));
}, [fetchApi]);

useEffect(() => {
const link = document.querySelector("link[rel=icon]");
const defaultLink = document.querySelector("link[rel=icon]:not([data-dark-mode])");
const darkModeLink = document.querySelector("link[rel=icon][data-dark-mode]");
const faviconHref = clientSettings?.application?.favicon;
const darkModeFaviconHref = clientSettings?.application?.faviconDark;
if (clientSettings) {
const link = document.querySelector("link[rel=icon]");
const defaultLink = document.querySelector("link[rel=icon]:not([data-dark-mode])");
const darkModeLink = document.querySelector("link[rel=icon][data-dark-mode]");
const faviconHref = clientSettings?.application?.favicon;
const darkModeFaviconHref = clientSettings?.application?.faviconDark;

if (faviconHref) {
link?.setAttribute("href", faviconHref);
defaultLink?.setAttribute("href", faviconHref);
}
if (faviconHref) {
link?.setAttribute("href", faviconHref);
defaultLink?.setAttribute("href", faviconHref);
}

if (darkModeFaviconHref) {
if (darkModeLink) {
darkModeLink.setAttribute("href", darkModeFaviconHref);
} else {
const newDarkModeLink = document.createElement("link");
newDarkModeLink.setAttribute("rel", "icon");
newDarkModeLink.setAttribute("href", darkModeFaviconHref);
newDarkModeLink.setAttribute("media", "(prefers-color-scheme: dark)");
newDarkModeLink.setAttribute("data-dark-mode", "true");
document.head.appendChild(newDarkModeLink);
if (darkModeFaviconHref) {
if (darkModeLink) {
darkModeLink.setAttribute("href", darkModeFaviconHref);
} else {
const newDarkModeLink = document.createElement("link");
newDarkModeLink.setAttribute("rel", "icon");
newDarkModeLink.setAttribute("href", darkModeFaviconHref);
newDarkModeLink.setAttribute("media", "(prefers-color-scheme: dark)");
newDarkModeLink.setAttribute("data-dark-mode", "true");
document.head.appendChild(newDarkModeLink);
}
} else if (darkModeLink) {
darkModeLink.remove();
}
} else if (darkModeLink) {
darkModeLink.remove();
}
}, [clientSettings]);

Expand Down
4 changes: 2 additions & 2 deletions src/Geopilot.Frontend/src/components/header/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const Header: FC<HeaderProps> = ({ openSubMenu }) => {
const navigate = useNavigate();
const location = useLocation();
const { clientSettings } = useAppSettings();
const { user, enabled, isAdmin, login, logout } = useGeopilotAuth();
const { user, authEnabled, isAdmin, login, logout } = useGeopilotAuth();

const [userMenuOpen, setUserMenuOpen] = useState<boolean>(false);

Expand Down Expand Up @@ -116,7 +116,7 @@ const Header: FC<HeaderProps> = ({ openSubMenu }) => {
</FlexRowBox>
<FlexRowBox>
<LanguagePopup />
{enabled &&
{authEnabled &&
(user ? (
<IconButton
sx={{
Expand Down
2 changes: 1 addition & 1 deletion src/Geopilot.Frontend/src/pages/delivery/delivery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const Delivery = () => {
const isCompleted = (stepIndex: number) => activeStep > stepIndex;

return (
<CenteredBox>
<CenteredBox data-cy="delivery">
<Typography variant="h1">{t("deliveryTitle")}</Typography>
<DeliveryContainer>
<Stepper activeStep={activeStep} orientation="vertical">
Expand Down
6 changes: 3 additions & 3 deletions src/Geopilot.Frontend/src/pages/delivery/deliveryContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const DeliveryProvider: FC<PropsWithChildren> = ({ children }) => {
const [isValidating, setIsValidating] = useState<boolean>(false);
const [abortControllers, setAbortControllers] = useState<AbortController[]>([]);
const { fetchApi } = useApi();
const { enabled } = useGeopilotAuth();
const { authEnabled } = useGeopilotAuth();
const [steps, setSteps] = useState<Map<DeliveryStepEnum, DeliveryStep>>(
new Map<DeliveryStepEnum, DeliveryStep>([
[DeliveryStepEnum.Upload, { label: "upload", content: <DeliveryUpload /> }],
Expand All @@ -49,7 +49,7 @@ export const DeliveryProvider: FC<PropsWithChildren> = ({ children }) => {
);

useEffect(() => {
if (enabled) {
if (authEnabled) {
setSteps(prevSteps => {
const newSteps = new Map(prevSteps);

Expand All @@ -68,7 +68,7 @@ export const DeliveryProvider: FC<PropsWithChildren> = ({ children }) => {
return newSteps;
});
}
}, [enabled]);
}, [authEnabled]);

const isActiveStep = (step: DeliveryStepEnum) => {
const stepKeys = Array.from(steps.keys());
Expand Down
4 changes: 2 additions & 2 deletions src/Geopilot.Frontend/src/pages/delivery/deliverySubmit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { useTranslation } from "react-i18next";

export const DeliverySubmit = () => {
const { t } = useTranslation();
const { enabled, user, login } = useGeopilotAuth();
const { authEnabled, user, login } = useGeopilotAuth();
const formMethods = useForm({ mode: "all" });
const { fetchApi } = useApi();
const { setStepError, validationResponse, isLoading, submitDelivery, resetDelivery } = useContext(DeliveryContext);
Expand Down Expand Up @@ -55,7 +55,7 @@ export const DeliverySubmit = () => {
submitDelivery(data as DeliverySubmitData);
};

return enabled && user ? (
return authEnabled && user ? (
<FormProvider {...formMethods}>
<form onSubmit={formMethods.handleSubmit(submitForm)}>
<FlexColumnBox>
Expand Down
6 changes: 3 additions & 3 deletions src/Geopilot.Frontend/src/pages/footer/about.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ export const About = () => {
const { hash } = useLocation();

useEffect(() => {
fetchApi<string>("info.md", { responseType: ContentType.Markdown }).then(setInfo);
fetchApi<PackageList>("license.json", { responseType: ContentType.Json }).then(setLicenseInfo);
fetchApi<PackageList>("license.custom.json", { responseType: ContentType.Json }).then(setLicenseInfoCustom);
fetchApi<string>("/info.md", { responseType: ContentType.Markdown }).then(setInfo);
fetchApi<PackageList>("/license.json", { responseType: ContentType.Json }).then(setLicenseInfo);
fetchApi<PackageList>("/license.custom.json", { responseType: ContentType.Json }).then(setLicenseInfoCustom);
fetchApi<string>("/api/v1/version").then(version => {
setVersion(version.split("+")[0]);
});
Expand Down
2 changes: 1 addition & 1 deletion src/Geopilot.Frontend/src/pages/footer/imprint.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const Imprint = () => {
const { fetchApi } = useApi();

useEffect(() => {
fetchApi<string>("imprint.md", { responseType: ContentType.Markdown }).then(setContent);
fetchApi<string>("/imprint.md", { responseType: ContentType.Markdown }).then(setContent);
}, [fetchApi]);

return (
Expand Down
Loading

0 comments on commit 291d783

Please sign in to comment.