diff --git a/src/components/collection-search.tsx b/src/components/collection-search.tsx index dacf278..ce4540e 100644 --- a/src/components/collection-search.tsx +++ b/src/components/collection-search.tsx @@ -1,6 +1,7 @@ -import { useMemo, useRef, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from "react"; import { LuSearch } from "react-icons/lu"; import { + Alert, CloseButton, Combobox, createListCollection, @@ -14,34 +15,44 @@ import { Stack, } from "@chakra-ui/react"; import { useQuery } from "@tanstack/react-query"; -import type { StacCollection } from "stac-ts"; -import { CollectionCard } from "./collections"; +import type { StacCollection, StacLink } from "stac-ts"; +import Collections, { CollectionCard } from "./collections"; +import useStacCollections from "../hooks/stac-collections"; import type { NaturalLanguageCollectionSearchResult } from "../types/stac"; +type CollectionSearchType = "Server" | "Client" | "Natural language"; + export default function CollectionSearch({ collections, catalogHref, setHref, + collectionSearchLink, }: { collections: StacCollection[]; catalogHref: string | undefined; setHref: (href: string | undefined) => void; + collectionSearchLink: StacLink | undefined; }) { - const [value, setValue] = useState<"Text" | "Natural language">("Text"); + const [value, setValue] = useState( + collectionSearchLink ? "Server" : "Client" + ); return ( - setValue(e.value as "Text" | "Natural language") - } + onValueChange={(e) => setValue(e.value as CollectionSearchType)} > - {value === "Text" && ( + {value === "Server" && collectionSearchLink && ( + + )} + {value === "Client" && ( void; + link: StacLink; +}) { + const [value, setValue] = useState(""); + const [query, setQuery] = useState(); + return ( + +
{ + e.preventDefault(); + setQuery(value); + }} + > + setValue(e.currentTarget.value)} + /> +
+ + {query && } +
+ ); +} + +function QueryResults({ + query, + setHref, + link, +}: { + query: string; + setHref: (href: string | undefined) => void; + link: StacLink; +}) { + const result = useStacCollections(link.href, query); + const [collections, setCollections] = useState(); + + useEffect(() => { + if (result.data) + setCollections( + result.data.pages.flatMap((page) => page?.collections || []) + ); + else setCollections(undefined); + }, [result.data]); + + if (result.error) + return ( + + + + Collection search error + {result.error.toString()} + + + ); + else if (collections) + return ; + else if (result.isFetching) return ; + else return null; +} + function CollectionCombobox({ collections, setHref, diff --git a/src/components/value.tsx b/src/components/value.tsx index 886b7a0..27f26b5 100644 --- a/src/components/value.tsx +++ b/src/components/value.tsx @@ -25,10 +25,13 @@ import { Button, ButtonGroup, Card, + CloseButton, + Dialog, Heading, HStack, Icon, Image, + Portal, Span, Stack, } from "@chakra-ui/react"; @@ -130,6 +133,13 @@ export function Value({ ); }, [assets]); + // TODO check for other versions + let hasFreeTextCollectionSearch = false; + if (value.conformsTo && Array.isArray(value.conformsTo)) + hasFreeTextCollectionSearch = value.conformsTo.includes( + "https://api.stacspec.org/v1.0.0-rc.1/collection-search#free-text" + ); + useEffect(() => { setCollections( collectionsResult.data?.pages.flatMap((page) => page?.collections || []) @@ -176,9 +186,36 @@ export function Value({ )} {!!value.description && ( - - {value.description as string} - + <> + + {value.description as string} + + + + + + + + + + + + + + {value.description as string} + + + + + + + + + + + )} {selfHref && ( @@ -309,6 +346,9 @@ export function Value({ collections={collections} setHref={setHref} catalogHref={value?.type === "Catalog" ? href : undefined} + collectionSearchLink={ + hasFreeTextCollectionSearch && collectionsLink + } /> )} diff --git a/src/constants.ts b/src/constants.ts index d9b4d2c..c3ac501 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -15,6 +15,11 @@ export const EXAMPLES = [ badge: "API", href: "https://openveda.cloud/api/stac", }, + { + title: "STAC Collection Discovery", + badge: "API", + href: "https://discover-api.dit.maap-project.org/", + }, { title: "Maxar Open Data", badge: "static", diff --git a/src/hooks/stac-collections.ts b/src/hooks/stac-collections.ts index 7fc8745..2cf3dee 100644 --- a/src/hooks/stac-collections.ts +++ b/src/hooks/stac-collections.ts @@ -1,9 +1,13 @@ import { useInfiniteQuery } from "@tanstack/react-query"; import type { StacCollections } from "../types/stac"; -export default function useStacCollections(href: string | undefined) { +export default function useStacCollections( + href: string | undefined, + query?: string +) { + const initialPageParam = query ? href + "?q=" + query : href; return useInfiniteQuery({ - queryKey: ["stac-collections", href], + queryKey: ["stac-collections", href, query], queryFn: async ({ pageParam }) => { if (pageParam) { return await fetch(pageParam).then((response) => { @@ -17,7 +21,7 @@ export default function useStacCollections(href: string | undefined) { return null; } }, - initialPageParam: href, + initialPageParam, getNextPageParam: (lastPage: StacCollections | null) => lastPage?.links?.find((link) => link.rel == "next")?.href, enabled: !!href,