Skip to content

Commit 8baeef7

Browse files
committed
refactor: pull out some logic into functions
1 parent fde7351 commit 8baeef7

File tree

3 files changed

+104
-85
lines changed

3 files changed

+104
-85
lines changed

src/components/value.tsx

Lines changed: 31 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ import {
3232
Span,
3333
Stack,
3434
} from "@chakra-ui/react";
35-
import { useInfiniteQuery, useQuery } from "@tanstack/react-query";
36-
import type { StacCatalog, StacCollection, StacItem, StacLink } from "stac-ts";
35+
import { useQuery } from "@tanstack/react-query";
36+
import type { StacCatalog, StacCollection, StacItem } from "stac-ts";
3737
import Assets from "./assets";
3838
import Catalogs from "./catalogs";
3939
import CollectionSearch from "./collection-search";
@@ -44,15 +44,10 @@ import Items from "./items";
4444
import Links from "./links";
4545
import Properties from "./properties";
4646
import { Prose } from "./ui/prose";
47+
import useStacCollections from "../hooks/stac-collections";
4748
import type { BBox2D } from "../types/map";
48-
import type {
49-
DatetimeBounds,
50-
StacAssets,
51-
StacCollections,
52-
StacSearch,
53-
StacValue,
54-
} from "../types/stac";
55-
import { fetchStac } from "../utils/stac";
49+
import type { DatetimeBounds, StacSearch, StacValue } from "../types/stac";
50+
import { deconstructStac, fetchStac, getImportantLinks } from "../utils/stac";
5651

5752
export interface SharedValueProps {
5853
catalogs: StacCatalog[] | undefined;
@@ -94,88 +89,51 @@ export function Value({
9489
const [numberOfCollections, setNumberOfCollections] = useState<number>();
9590
const [fetchAllCollections, setFetchAllCollections] = useState(false);
9691
const [thumbnailError, setThumbnailError] = useState(false);
92+
9793
const selfHref = value.links?.find((link) => link.rel === "self")?.href;
94+
9895
const { links, assets, properties } = useMemo(() => {
99-
if (value) {
100-
if (value.type === "Feature") {
101-
return {
102-
links: value.links,
103-
assets: value.assets as StacAssets | undefined,
104-
properties: value.properties,
105-
};
106-
} else {
107-
const { links, assets, ...properties } = value;
108-
return { links, assets: assets as StacAssets | undefined, properties };
109-
}
110-
} else {
111-
return { links: undefined, assets: undefined, properties: undefined };
112-
}
96+
return deconstructStac(value);
11397
}, [value]);
98+
// Description is handled at the top of the panel, so we don't need it down in
99+
// the properties.
100+
if (properties?.description) delete properties["description"];
101+
114102
const { rootLink, collectionsLink, nextLink, prevLink, filteredLinks } =
115103
useMemo(() => {
116-
let rootLink: StacLink | undefined = undefined;
117-
let collectionsLink: StacLink | undefined = undefined;
118-
let nextLink: StacLink | undefined = undefined;
119-
let prevLink: StacLink | undefined = undefined;
120-
const filteredLinks = [];
121-
if (links) {
122-
for (const link of links) {
123-
switch (link.rel) {
124-
case "root":
125-
rootLink = link;
126-
break;
127-
case "data":
128-
collectionsLink = link;
129-
break;
130-
case "next":
131-
nextLink = link;
132-
break;
133-
case "previous":
134-
prevLink = link;
135-
break;
136-
}
137-
// We already show children and items in their own pane
138-
if (link.rel !== "child" && link.rel !== "item")
139-
filteredLinks.push(link);
140-
}
141-
}
142-
return { rootLink, collectionsLink, nextLink, prevLink, filteredLinks };
104+
return getImportantLinks(links);
143105
}, [links]);
106+
144107
const rootData = useQuery<StacValue | undefined>({
145108
queryKey: ["stac-value", rootLink?.href],
146109
enabled: !!rootLink,
147110
queryFn: () => rootLink && fetchStac(rootLink.href),
148111
});
112+
149113
const searchLinks = useMemo(() => {
150114
return rootData.data?.links?.filter((link) => link.rel === "search");
151115
}, [rootData.data]);
152-
const collectionsResult = useInfiniteQuery({
153-
queryKey: ["stac-collections", collectionsLink?.href],
154-
queryFn: async ({ pageParam }) => {
155-
if (pageParam) {
156-
return await fetch(pageParam).then((response) => {
157-
if (response.ok) return response.json();
158-
else
159-
throw new Error(
160-
`Error while fetching collections from ${pageParam}`
161-
);
162-
});
163-
} else {
164-
return null;
165-
}
166-
},
167-
initialPageParam: collectionsLink?.href,
168-
getNextPageParam: (lastPage: StacCollections | null) =>
169-
lastPage?.links?.find((link) => link.rel == "next")?.href,
170-
enabled: !!collectionsLink,
171-
});
116+
117+
const collectionsResult = useStacCollections(collectionsLink?.href);
118+
119+
const thumbnailAsset = useMemo(() => {
120+
return (
121+
assets &&
122+
((Object.keys(assets).includes("thumbnail") && assets["thumbnail"]) ||
123+
Object.values(assets).find((asset) =>
124+
asset.roles?.includes("thumbnail")
125+
))
126+
);
127+
}, [assets]);
128+
172129
useEffect(() => {
173130
setCollections(
174131
collectionsResult.data?.pages.flatMap((page) => page?.collections || [])
175132
);
176133
if (collectionsResult.data?.pages.at(0)?.numberMatched)
177134
setNumberOfCollections(collectionsResult.data?.pages[0]?.numberMatched);
178135
}, [collectionsResult.data, setCollections]);
136+
179137
useEffect(() => {
180138
if (
181139
fetchAllCollections &&
@@ -184,23 +142,12 @@ export function Value({
184142
)
185143
collectionsResult.fetchNextPage();
186144
}, [fetchAllCollections, collectionsResult]);
145+
187146
useEffect(() => {
188147
setFetchAllCollections(false);
189148
setNumberOfCollections(undefined);
190149
}, [value]);
191150

192-
// Handled by the value
193-
if (properties?.description) delete properties["description"];
194-
const thumbnailAsset = useMemo(() => {
195-
return (
196-
assets &&
197-
((Object.keys(assets).includes("thumbnail") && assets["thumbnail"]) ||
198-
Object.values(assets).find((asset) =>
199-
asset.roles?.includes("thumbnail")
200-
))
201-
);
202-
}, [assets]);
203-
204151
useEffect(() => {
205152
setItems(undefined);
206153
}, [search, setItems]);
@@ -220,6 +167,7 @@ export function Value({
220167
<Image
221168
src={thumbnailAsset.href}
222169
onError={() => setThumbnailError(true)}
170+
maxH={"200"}
223171
/>
224172
)}
225173

src/hooks/stac-collections.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { useInfiniteQuery } from "@tanstack/react-query";
2+
import type { StacCollections } from "../types/stac";
3+
4+
export default function useStacCollections(href: string | undefined) {
5+
return useInfiniteQuery({
6+
queryKey: ["stac-collections", href],
7+
queryFn: async ({ pageParam }) => {
8+
if (pageParam) {
9+
return await fetch(pageParam).then((response) => {
10+
if (response.ok) return response.json();
11+
else
12+
throw new Error(
13+
`Error while fetching collections from ${pageParam}`
14+
);
15+
});
16+
} else {
17+
return null;
18+
}
19+
},
20+
initialPageParam: href,
21+
getNextPageParam: (lastPage: StacCollections | null) =>
22+
lastPage?.links?.find((link) => link.rel == "next")?.href,
23+
enabled: !!href,
24+
});
25+
}

src/utils/stac.ts

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { UseFileUploadReturn } from "@chakra-ui/react";
2-
import type { StacCollection, StacItem } from "stac-ts";
2+
import type { StacCollection, StacItem, StacLink } from "stac-ts";
33
import type { BBox2D } from "../types/map";
4-
import type { DatetimeBounds, StacValue } from "../types/stac";
4+
import type { DatetimeBounds, StacAssets, StacValue } from "../types/stac";
55

66
export async function getStacJsonValue(
77
href: string,
@@ -204,3 +204,49 @@ export function isItemInDatetimeBounds(item: StacItem, bounds: DatetimeBounds) {
204204
(datetimes.start && datetimes.start > bounds.end)
205205
);
206206
}
207+
208+
export function deconstructStac(value: StacValue) {
209+
if (value.type === "Feature") {
210+
return {
211+
links: value.links,
212+
assets: value.assets as StacAssets | undefined,
213+
properties: value.properties,
214+
};
215+
} else {
216+
const { links, assets, ...properties } = value;
217+
return {
218+
links: links || [],
219+
assets: assets as StacAssets | undefined,
220+
properties,
221+
};
222+
}
223+
}
224+
225+
export function getImportantLinks(links: StacLink[]) {
226+
let rootLink: StacLink | undefined = undefined;
227+
let collectionsLink: StacLink | undefined = undefined;
228+
let nextLink: StacLink | undefined = undefined;
229+
let prevLink: StacLink | undefined = undefined;
230+
const filteredLinks = [];
231+
if (links) {
232+
for (const link of links) {
233+
switch (link.rel) {
234+
case "root":
235+
rootLink = link;
236+
break;
237+
case "data":
238+
collectionsLink = link;
239+
break;
240+
case "next":
241+
nextLink = link;
242+
break;
243+
case "previous":
244+
prevLink = link;
245+
break;
246+
}
247+
// We already show children and items in their own pane
248+
if (link.rel !== "child" && link.rel !== "item") filteredLinks.push(link);
249+
}
250+
}
251+
return { rootLink, collectionsLink, nextLink, prevLink, filteredLinks };
252+
}

0 commit comments

Comments
 (0)