Skip to content

Commit 5e230a6

Browse files
committed
chg: handle load config with absolute urls
1 parent ecac61e commit 5e230a6

File tree

4 files changed

+32
-38
lines changed

4 files changed

+32
-38
lines changed

src/components/Header.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export function Header({ icon }: { icon: string }) {
66
<div className="container mx-auto px-4 py-8">
77
<div className="flex items-center justify-between">
88
<div className="flex items-center gap-4">
9-
<img src={icon} className="h-12 w-auto" />
9+
{icon && <img src={icon} className="h-12 w-auto" />}
1010
<div>
1111
<div className="text-3xl font-bold">NINA</div>
1212
<div className="text-sm opacity-90">Norsk institutt for naturforskning</div>

src/routes/$mapId.tsx

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,33 @@
11
import { ErrorComponentProps, Outlet, ErrorComponent, createFileRoute, Link } from '@tanstack/react-router';
2-
import { DEFAULT_LANG, mapConfigQueryOptions } from '../config';
3-
import { useSuspenseQuery } from '@tanstack/react-query';
2+
import { DEFAULT_LANG, mapConfigQueryOptions, storeConfigQueryOptions } from '../config';
43
import { Fragment, useEffect } from 'react';
54
import { AxiosError } from 'axios';
6-
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
7-
import { faSpinner } from '@fortawesome/free-solid-svg-icons';
85
import { useAppStore } from '../hooks/app';
96
import { useUIActions, useUIStore } from '../hooks/ui';
107
import { Head } from '../components/Head';
118
import { useTranslation } from 'react-i18next';
129
import { Header } from '../components/Header';
1310
import { Footer } from '../components/HomeFooter';
1411

12+
class MapNotFoundError extends Error {}
13+
1514
export const Route = createFileRoute('/$mapId')({
1615
component: RootComponent,
17-
loader: ({ params: { mapId }, context: { queryClient } }) => {
18-
return queryClient.ensureQueryData(
19-
mapConfigQueryOptions(`${useUIStore.getState().defaultConfig}/${mapId}/config.json`),
20-
);
16+
loader: async ({ params: { mapId }, context: { queryClient } }) => {
17+
const config = useUIStore.getState().defaultConfig;
18+
const storeResponse = await queryClient.fetchQuery(storeConfigQueryOptions(config));
19+
const map = storeResponse.data.maps.find(m => m.id === mapId);
20+
if (map) {
21+
const configResponse = await queryClient.fetchQuery(mapConfigQueryOptions(map.url));
22+
return configResponse.data;
23+
}
24+
throw new MapNotFoundError(mapId);
2125
},
2226
errorComponent: ConfigErrorComponent,
2327
});
2428

2529
function ConfigErrorComponent({ error }: ErrorComponentProps) {
26-
if (error instanceof AxiosError) {
30+
if (error instanceof AxiosError || MapNotFoundError) {
2731
return (
2832
<div className="min-h-screen bg-base-100 flex flex-col">
2933
<Header icon="" />
@@ -56,20 +60,15 @@ function ConfigErrorComponent({ error }: ErrorComponentProps) {
5660
}
5761

5862
function RootComponent() {
59-
const defaultConfigPath = useUIStore(state => state.defaultConfig);
60-
const ready = useUIStore(state => state.ready);
61-
const { mapId } = Route.useParams();
62-
const { isLoading, data: config } = useSuspenseQuery(
63-
mapConfigQueryOptions(`${defaultConfigPath}/${mapId}/config.json`),
64-
);
63+
const config = Route.useLoaderData();
6564
const uiActions = useUIActions();
6665
const { i18n } = useTranslation();
6766

6867
useEffect(() => {
69-
useAppStore.setState(() => config.data);
68+
useAppStore.setState(() => config);
7069
if (i18n?.changeLanguage) {
7170
i18n
72-
.changeLanguage(config.data.config.language ?? DEFAULT_LANG)
71+
.changeLanguage(config.config.language ?? DEFAULT_LANG)
7372
.then(() => uiActions.setReady(true))
7473
.catch(console.error);
7574
} else {
@@ -79,15 +78,7 @@ function RootComponent() {
7978
return () => {
8079
uiActions.setReady(false);
8180
};
82-
}, [uiActions, config.data, i18n]);
83-
84-
if (isLoading || !ready) {
85-
return (
86-
<div className="flex justify-center items-center w-screen h-screen bg-primary/20">
87-
<FontAwesomeIcon icon={faSpinner} spin />
88-
</div>
89-
);
90-
}
81+
}, [uiActions, config, i18n]);
9182

9283
return (
9384
<Fragment>

src/routes/index.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { createFileRoute, ErrorComponent, ErrorComponentProps, Link } from '@tanstack/react-router';
2-
import { storeConfigQueryOptions } from '../config';
32
import { useUIStore } from '../hooks/ui';
4-
import { useSuspenseQuery } from '@tanstack/react-query';
5-
import { AxiosError } from 'axios';
63
import { Header } from '../components/Header';
74
import { Footer } from '../components/HomeFooter';
5+
import { AxiosError } from 'axios';
6+
import { storeConfigQueryOptions } from '../config';
7+
import { useSuspenseQuery } from '@tanstack/react-query';
88

99
function ConfigErrorComponent({ error }: ErrorComponentProps) {
1010
if (error instanceof AxiosError) {
@@ -36,18 +36,18 @@ function ConfigErrorComponent({ error }: ErrorComponentProps) {
3636
export const Route = createFileRoute('/')({
3737
component: RouteComponent,
3838
loader: ({ context: { queryClient } }) => {
39-
return queryClient.ensureQueryData(storeConfigQueryOptions(`${useUIStore.getState().defaultConfig}/maps.json`));
39+
return queryClient.ensureQueryData(storeConfigQueryOptions(useUIStore.getState().defaultConfig));
4040
},
4141
errorComponent: ConfigErrorComponent,
4242
});
4343

4444
function RouteComponent() {
4545
const defaultConfigPath = useUIStore(state => state.defaultConfig);
46-
const { isLoading, data, isError } = useSuspenseQuery(storeConfigQueryOptions(`${defaultConfigPath}/maps.json`));
46+
const { data, isLoading, isError } = useSuspenseQuery(storeConfigQueryOptions(defaultConfigPath));
4747

4848
return (
4949
<div className="min-h-screen bg-base-100 flex flex-col">
50-
<Header icon={defaultConfigPath + data.data.icon} />
50+
<Header icon={data.data.icon} />
5151

5252
<main className="container mx-auto px-4 py-8 grow">
5353
<div className="mb-8">

src/types.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -212,11 +212,14 @@ export interface PMTileSource extends Partial<Source> {
212212

213213
export type LayerConfig = TitilerSource | PMTileSource | RasterSource | Partial<Source>;
214214

215+
export interface StoreMap {
216+
title: string;
217+
description?: string;
218+
id: string;
219+
url: string;
220+
}
221+
215222
export interface StoreConfig {
216223
icon: string;
217-
maps: {
218-
title: string;
219-
description?: string;
220-
id: string;
221-
}[];
224+
maps: StoreMap[];
222225
}

0 commit comments

Comments
 (0)