From 64833dcbc5f73239eeadef290c70ab32c7e5358e Mon Sep 17 00:00:00 2001 From: Sandra Hoang Date: Tue, 2 Dec 2025 11:58:31 -0500 Subject: [PATCH 1/2] add stac-react prov and collections aggregate --- src/components/value.tsx | 89 +++++++++++++++++++++++++++++++++------- src/layers/overlay.tsx | 22 ++++++---- 2 files changed, 88 insertions(+), 23 deletions(-) diff --git a/src/components/value.tsx b/src/components/value.tsx index 167d329..849375b 100644 --- a/src/components/value.tsx +++ b/src/components/value.tsx @@ -37,11 +37,13 @@ import ItemsSection from "./sections/items"; import LinksSection from "./sections/links"; import PropertiesSection from "./sections/properties"; import { Prose } from "./ui/prose"; -import useStacCollections from "../hooks/stac-collections"; +// import useStacCollections from "../hooks/stac-collections"; import type { BBox2D } from "../types/map"; import type { DatetimeBounds, StacSearch, StacValue } from "../types/stac"; import { deconstructStac, fetchStac, getImportantLinks } from "../utils/stac"; +import { useCollections } from "@developmentseed/stac-react"; + export interface SharedValueProps { catalogs: StacCatalog[] | undefined; setCollections: (collections: StacCollection[] | undefined) => void; @@ -86,6 +88,7 @@ export function Value({ const [numberOfCollections, setNumberOfCollections] = useState(); const [fetchAllCollections, setFetchAllCollections] = useState(false); const [thumbnailError, setThumbnailError] = useState(false); + const [collectionsAggregate, setCollectionsAggregate] = useState([]); const selfHref = value.links?.find((link) => link.rel === "self")?.href; @@ -111,7 +114,8 @@ export function Value({ return rootData.data?.links?.filter((link) => link.rel === "search"); }, [rootData.data]); - const collectionsResult = useStacCollections(collectionsLink?.href); + const collectionsResult = useCollections(); + console.log(`collectionsResult: `, collectionsResult) const thumbnailAsset = useMemo(() => { return ( @@ -124,21 +128,36 @@ export function Value({ }, [assets]); useEffect(() => { - setCollections( - collectionsResult.data?.pages.flatMap((page) => page?.collections || []) - ); - if (collectionsResult.data?.pages.at(0)?.numberMatched) - setNumberOfCollections(collectionsResult.data?.pages[0]?.numberMatched); - }, [collectionsResult.data, setCollections]); + if (!fetchAllCollections) { + setCollections( + collectionsResult.collections?.collections || [] + ); + if (collectionsResult.collections?.numberMatched) + setNumberOfCollections(collectionsResult.collections?.numberMatched); + } + }, [collectionsResult, setCollections]); + + useEffect(() => { + if (collectionsResult.collections && fetchAllCollections) { + setCollectionsAggregate((previous) => [...previous, ...collectionsResult.collections?.collections || []]); + } + }, [fetchAllCollections, collectionsResult.collections]); useEffect(() => { if ( fetchAllCollections && - !collectionsResult.isFetching && - collectionsResult.hasNextPage - ) - collectionsResult.fetchNextPage(); - }, [fetchAllCollections, collectionsResult]); + collectionsResult.nextPage + ) { + collectionsResult.nextPage?.(); + } + }, [fetchAllCollections, collectionsResult.nextPage]); + + useEffect(() => { + if (numberOfCollections == collectionsAggregate.length) { + console.log(`setting collections because of match`); + setCollections(collectionsAggregate); + } + }, [numberOfCollections, collectionsAggregate]); useEffect(() => { setFetchAllCollections(false); @@ -149,6 +168,11 @@ export function Value({ setItems(undefined); }, [search, setItems]); + // console.log(`collections: `, collections) + console.log(`numberMatched: `, numberOfCollections) + console.log(`collectionsAggregate.length: `, collectionsAggregate.length) + console.log(`collectionsResult: `, collectionsResult) + console.log(`collectionsAggregate: `, collectionsAggregate) return ( @@ -224,7 +248,7 @@ export function Value({ )} - {collectionsResult.hasNextPage && ( + {/* {collectionsResult.hasNextPage && ( Collection pagination @@ -259,8 +283,45 @@ export function Value({ + )} */} + + {collectionsResult.nextPage && ( + + + Collection pagination + + + + + + + + )} + {catalogs && catalogs.length > 0 && ( diff --git a/src/layers/overlay.tsx b/src/layers/overlay.tsx index 7150771..3b8711f 100644 --- a/src/layers/overlay.tsx +++ b/src/layers/overlay.tsx @@ -16,6 +16,8 @@ import Panel, { type PanelProps } from "../components/panel"; import { ColorModeButton } from "../components/ui/color-mode"; import type { StacValue } from "../types/stac"; +import { StacApiProvider } from "@developmentseed/stac-react"; + export interface OverlayProps extends PanelProps { picked: StacValue | undefined; setPicked: (picked: StacValue | undefined) => void; @@ -57,15 +59,17 @@ export default function Overlay({ )) || stac-map} - + + + From 20cb2c5f1a68dbf851beedecdec1c79b0ffe4359 Mon Sep 17 00:00:00 2001 From: Sandra Hoang Date: Wed, 3 Dec 2025 16:30:45 -0500 Subject: [PATCH 2/2] move provider --- src/app.tsx | 158 +++++++++++++++++++++------------------ src/components/panel.tsx | 2 +- src/components/value.tsx | 63 +--------------- src/layers/overlay.tsx | 22 +++--- 4 files changed, 98 insertions(+), 147 deletions(-) diff --git a/src/app.tsx b/src/app.tsx index cf4b09c..c7426c2 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -16,6 +16,7 @@ import { isItemInDatetimeBounds, isVisual, } from "./utils/stac"; +import { StacApiProvider } from "@developmentseed/stac-react"; // TODO make this configurable by the user. const lineColor: Color = [207, 63, 2, 100]; @@ -33,6 +34,8 @@ export default function App() { const [filter, setFilter] = useState(true); const [stacGeoparquetItemId, setStacGeoparquetItemId] = useState(); const [cogTileHref, setCogTileHref] = useState(); + const [filteredCollections, setFilteredCollections] = useState(); + const [collections, setFinalCollections] = useState(); // Derived state const { @@ -52,20 +55,9 @@ export default function App() { value, enabled: !!value && !collectionsLink, }); - const collections = collectionsLink ? userCollections : linkedCollections; + const items = userItems || linkedItems; - const filteredCollections = useMemo(() => { - if (filter && collections) { - return collections.filter( - (collection) => - (!bbox || isCollectionInBbox(collection, bbox)) && - (!datetimeBounds || - isCollectionInDatetimeBounds(collection, datetimeBounds)) - ); - } else { - return undefined; - } - }, [collections, filter, bbox, datetimeBounds]); + const filteredItems = useMemo(() => { if (filter && items) { return items.filter( @@ -79,6 +71,22 @@ export default function App() { }, [items, filter, bbox, datetimeBounds]); // Effects + useEffect(() => { + setFinalCollections(collectionsLink ? userCollections : linkedCollections); + }, [collectionsLink, userCollections, linkedCollections]); + + useEffect(() => { + if(filter && collections) { + const filtered = collections.filter( + (collection) => + (!bbox || isCollectionInBbox(collection, bbox)) && + (!datetimeBounds || + isCollectionInDatetimeBounds(collection, datetimeBounds)) + ); + setFilteredCollections(filtered ?? undefined) + } + }, [filter, collections, userCollections, bbox, datetimeBounds]); + useEffect(() => { function handlePopState() { setHref(new URLSearchParams(location.search).get("href") ?? ""); @@ -137,67 +145,69 @@ export default function App() { return ( <> - - - - - - - - - - - + + + + + + + + + + + + + ); } diff --git a/src/components/panel.tsx b/src/components/panel.tsx index 8976a9f..4e1c682 100644 --- a/src/components/panel.tsx +++ b/src/components/panel.tsx @@ -34,7 +34,7 @@ export default function Panel({ ); else if (href) { if (value) { - return ; + return ; } else { return ; } diff --git a/src/components/value.tsx b/src/components/value.tsx index 849375b..77262ea 100644 --- a/src/components/value.tsx +++ b/src/components/value.tsx @@ -88,7 +88,6 @@ export function Value({ const [numberOfCollections, setNumberOfCollections] = useState(); const [fetchAllCollections, setFetchAllCollections] = useState(false); const [thumbnailError, setThumbnailError] = useState(false); - const [collectionsAggregate, setCollectionsAggregate] = useState([]); const selfHref = value.links?.find((link) => link.rel === "self")?.href; @@ -128,18 +127,13 @@ export function Value({ }, [assets]); useEffect(() => { - if (!fetchAllCollections) { + if (fetchAllCollections) { + setCollections((previous) => [...previous, ...collectionsResult.collections?.collections || []]); + } else { setCollections( collectionsResult.collections?.collections || [] ); - if (collectionsResult.collections?.numberMatched) - setNumberOfCollections(collectionsResult.collections?.numberMatched); - } - }, [collectionsResult, setCollections]); - - useEffect(() => { - if (collectionsResult.collections && fetchAllCollections) { - setCollectionsAggregate((previous) => [...previous, ...collectionsResult.collections?.collections || []]); + setNumberOfCollections(collectionsResult.collections?.numberMatched); } }, [fetchAllCollections, collectionsResult.collections]); @@ -152,13 +146,6 @@ export function Value({ } }, [fetchAllCollections, collectionsResult.nextPage]); - useEffect(() => { - if (numberOfCollections == collectionsAggregate.length) { - console.log(`setting collections because of match`); - setCollections(collectionsAggregate); - } - }, [numberOfCollections, collectionsAggregate]); - useEffect(() => { setFetchAllCollections(false); setNumberOfCollections(undefined); @@ -168,11 +155,6 @@ export function Value({ setItems(undefined); }, [search, setItems]); - // console.log(`collections: `, collections) - console.log(`numberMatched: `, numberOfCollections) - console.log(`collectionsAggregate.length: `, collectionsAggregate.length) - console.log(`collectionsResult: `, collectionsResult) - console.log(`collectionsAggregate: `, collectionsAggregate) return ( @@ -248,43 +230,6 @@ export function Value({ )} - {/* {collectionsResult.hasNextPage && ( - - - Collection pagination - - - - - - - - - )} */} - {collectionsResult.nextPage && ( diff --git a/src/layers/overlay.tsx b/src/layers/overlay.tsx index 3b8711f..7150771 100644 --- a/src/layers/overlay.tsx +++ b/src/layers/overlay.tsx @@ -16,8 +16,6 @@ import Panel, { type PanelProps } from "../components/panel"; import { ColorModeButton } from "../components/ui/color-mode"; import type { StacValue } from "../types/stac"; -import { StacApiProvider } from "@developmentseed/stac-react"; - export interface OverlayProps extends PanelProps { picked: StacValue | undefined; setPicked: (picked: StacValue | undefined) => void; @@ -59,17 +57,15 @@ export default function Overlay({ )) || stac-map} - - - +