Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | 356x 356x 714x 714x 357x 358x 358x 357x 357x 1x 1x 357x 357x 357x 357x 714x 1x 357x 1x 357x 357x | import { ReactElement, useEffect, useState } from "react";
import { BrowserRouter } from "react-router";
import styled from "styled-components";
import { AppRoutes } from "client/app/AppRoutes";
import { Header } from "client/components/Header";
import { loadData } from "client/utils/loadData";
import { Loading } from "client/components/Loading";
import { getIconLibrary } from "client/utils/icons";
import { config } from "shared/config";
import { ErrorBar } from "client/components/ErrorBar";
import { MOBILE_MARGIN } from "client/globalStyle";
import { TestTime } from "client/test/test-components/TestTime";
import { TestGenerateSerial } from "client/test/test-components/TestGenerateSerial";
import { Announcement } from "client/components/Announcement";
import { AdminMessageBanner } from "client/components/AdminMessageBanner";
import { NotificationBar } from "client/views/event-log/NotificationBar";
import { resetNetworkError } from "client/views/admin/adminUtils";
import { HistoryProvider } from "client/app/HistoryContext";
const { loadedSettings, showTestValues, showAnnouncement, dataUpdateInterval } =
config.client();
const App = (): ReactElement => {
const [loading, setLoading] = useState<boolean>(true);
useEffect(() => {
const fetchData = async (): Promise<void> => {
await loadData();
setLoading(false);
};
// eslint-disable-next-line @typescript-eslint/no-floating-promises
fetchData();
// eslint-disable-next-line @typescript-eslint/no-misused-promises
const updateTimer = setInterval(async () => {
resetNetworkError();
await fetchData();
}, dataUpdateInterval * 1000);
// The network error toast can appear right before the laptop sleeps
// (Wi-Fi drops before JS is suspended), so clear it when connectivity is
// lost and refresh immediately when it returns instead of leaving the
// toast visible until the next poll cycle
const handleOnline = async (): Promise<void> => {
resetNetworkError();
await fetchData();
};
addEventListener("offline", resetNetworkError);
// eslint-disable-next-line @typescript-eslint/no-misused-promises
addEventListener("online", handleOnline);
return () => {
clearInterval(updateTimer);
removeEventListener("offline", resetNetworkError);
// eslint-disable-next-line @typescript-eslint/no-misused-promises
removeEventListener("online", handleOnline);
};
}, []);
getIconLibrary();
return (
<>
{loading && <Loading />}
{!loading && (
<BrowserRouter>
<HistoryProvider>
{loadedSettings !== "production" && showTestValues && (
<TestValueContainer>
<TestTime />
<TestGenerateSerial />
</TestValueContainer>
)}
<Header />
<ErrorBar />
<AdminMessageBanner />
<NotificationBar />
{showAnnouncement && <Announcement />}
<AppContainer>
<AppRoutes />
</AppContainer>
</HistoryProvider>
</BrowserRouter>
)}
</>
);
};
const TestValueContainer = styled.div`
position: fixed;
top: 0;
left: 0;
z-index: 1000;
/* Don't block clicks on the header underneath; children opt back in */
pointer-events: none;
@media (max-width: ${(props) => props.theme.breakpointDesktop}) {
display: none;
}
`;
const AppContainer = styled.div`
@media (max-width: ${(props) => props.theme.breakpointPhone}) {
margin-left: ${MOBILE_MARGIN}px;
margin-right: ${MOBILE_MARGIN}px;
}
@media (max-width: ${(props) => props.theme.breakpointDesktop}) {
margin-left: ${MOBILE_MARGIN}px;
margin-right: ${MOBILE_MARGIN}px;
}
`;
export default App;
|