Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 31 additions & 30 deletions frontend/src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ import {useDate} from "../context/date-context";
import {SnackbarMessage} from "../types/ui";
import {backend} from "../util/util";
import {AboutInformation} from "./dialogs/AboutInformation";
import {LeafletWorldMap} from "./leaflet/LeafletWorldMap";
import {ExternalLink} from "./link/ExternalLink";
import {LoadingAnimation} from "./loading/LoadingAnimation";

// Lazy loaded components
const ExternalLink = React.lazy(() => import('./link/ExternalLink'));
// Lazy loaded components. The map is part of the entry (it is always needed), so its chunk is requested together with
// the entry script instead of after it. The overlay has its own Suspense boundary, so the map does not wait for it.
const OverlayLarge = React.lazy(() => import('./overlay/OverlayLarge'));
const OverlaySmall = React.lazy(() => import('./overlay/OverlaySmall'));
const LeafletWorldMap = React.lazy(() => import('./leaflet/LeafletWorldMap'));

export const App: FunctionComponent = () => {
// Component state
Expand Down Expand Up @@ -46,34 +47,34 @@ export const App: FunctionComponent = () => {

return (
<>
<Suspense fallback={<LoadingAnimation/>}>
<React.StrictMode>
{isLoading ? <LoadingAnimation/> : null}
</React.StrictMode>
<LeafletWorldMap
setIsLoading={setIsLoading}
/>
<React.StrictMode>
<React.StrictMode>
{isLoading ? <LoadingAnimation/> : null}
</React.StrictMode>
<LeafletWorldMap
setIsLoading={setIsLoading}
/>
<React.StrictMode>
<Suspense fallback={null}>
{isLargeScreen ? <OverlayLarge/> : <OverlaySmall/>}
<Box sx={{
color: "#b4b4b4",
background: "#262626",
position: "fixed",
right: "2px",
bottom: "2px",
fontSize: ".7rem",
}}>
<span>
<ExternalLink href="https://leafletjs.com" label={"Leaflet"}/>
{" | © "}
<ExternalLink href="https://www.openstreetmap.org/copyright" label={"OpenStreetMap"}/>
{" contributors © "}
<ExternalLink href="https://carto.com/attributions" label={"CARTO"}/>
</span>
</Box>
<AboutInformation/>
</React.StrictMode>
</Suspense>
</Suspense>
<Box sx={{
color: "#b4b4b4",
background: "#262626",
position: "fixed",
right: "2px",
bottom: "2px",
fontSize: ".7rem",
}}>
<span>
<ExternalLink href="https://leafletjs.com" label={"Leaflet"}/>
{" | © "}
<ExternalLink href="https://www.openstreetmap.org/copyright" label={"OpenStreetMap"}/>
{" contributors © "}
<ExternalLink href="https://carto.com/attributions" label={"CARTO"}/>
</span>
</Box>
<AboutInformation/>
</React.StrictMode>
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,11 @@ export const ResponsiveRelayDetailsDialog: FunctionComponent = () => {
}
}

// Discard the previous relays as soon as the relays of another location are passed to the dialog
const [syncedRelayDetailsIdToLocationMap, setSyncedRelayDetailsIdToLocationMap] = useState(relayDetailsIdToLocationMap)
// Discard the previous relays as soon as the relays of another location are passed to the dialog.
// Starts without a value, because the dialog is only mounted when it is opened for the first time, so the relays of
// that first location have to count as a change too.
const [syncedRelayDetailsIdToLocationMap, setSyncedRelayDetailsIdToLocationMap] =
useState<Map<number, RelayLocationDto>>()
if (syncedRelayDetailsIdToLocationMap !== relayDetailsIdToLocationMap) {
setSyncedRelayDetailsIdToLocationMap(relayDetailsIdToLocationMap)
setRelayDetailsMatch(undefined)
Expand Down
18 changes: 13 additions & 5 deletions frontend/src/components/leaflet/LeafletLayers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,22 @@ export const LeafletLayers: FunctionComponent<Props> = ({relays, reloadSelectedD
// Component state
const [showFamilySelectionDialog, setShowFamilySelectionDialog] = useState(false)
const [familiesForSelectionDialog, setFamiliesForSelectionDialog] = useState<number[]>([])
// The dialogs are separate chunks and are only loaded when they are opened for the first time. They stay mounted
// afterwards, so they can close with their transition.
const [hasOpenedRelayDetailsDialog, setHasOpenedRelayDetailsDialog] = useState(false)
const [hasOpenedFamilySelectionDialog, setHasOpenedFamilySelectionDialog] = useState(false)
const [leafletMarkerLayers] = useState<LayerGroup>(new LayerGroup())
// The country borders are a separate chunk, which is only loaded once the countries are shown
const [worldFeatures, setWorldFeatures] = useState<CountryFeature[]>()

// Atom state
const [, setShowRelayDetailsDialog] = useAtom(showRelayDetailsDialogAtom)
const [showRelayDetailsDialog, setShowRelayDetailsDialog] = useAtom(showRelayDetailsDialogAtom)
const [, setRelaysForDetailsDialog] = useAtom(relaysForDetailsDialogAtom)
const [, setRelayDetailsDialogSearch] = useAtom(relayDetailsDialogSearchAtom)
const [, setFilteredRelays] = useAtom(filteredRelaysAtom)
const [relaySearchOnMap, setRelaySearchOnMap] = useAtom(relaySearchOnMapAtom)
if (showRelayDetailsDialog && !hasOpenedRelayDetailsDialog) setHasOpenedRelayDetailsDialog(true)
if (showFamilySelectionDialog && !hasOpenedFamilySelectionDialog) setHasOpenedFamilySelectionDialog(true)

// App context
const leafletMap = useMap()
Expand Down Expand Up @@ -251,15 +257,17 @@ export const LeafletLayers: FunctionComponent<Props> = ({relays, reloadSelectedD
}
}, [filteredRelays, setFilteredRelays, leafletMarkerLayers, relays, statistics, setStatistics, filteredRelaysByFlags.length, settings, relayFamilyMap, leafletMap, relayCountryMap, closeSnackbar, enqueueSnackbar, setSettings, relayLocationHeatmapLayer, countryBordersLayer, aggregatedCoordinatesLayer, relayCountryLayer, relayLayer, relaySelectedFamilyLayer, relayFamilyCoordinatesLayer])

const closeFamilySelectionDialog = useCallback(() => setShowFamilySelectionDialog(false), [])

return (
<Suspense fallback={<LoadingAnimation/>}>
<ResponsiveRelayDetailsDialog/>
<FamilySelectionDialog
{hasOpenedRelayDetailsDialog ? <ResponsiveRelayDetailsDialog/> : null}
{hasOpenedFamilySelectionDialog ? <FamilySelectionDialog
shouldShowDialog={showFamilySelectionDialog}
closeDialog={useCallback(() => setShowFamilySelectionDialog(false), [])}
closeDialog={closeFamilySelectionDialog}
reloadSelectedDay={reloadSelectedDay}
familyIds={familiesForSelectionDialog}
/>
/> : null}
</Suspense>
);
};
Loading