Skip to content
Draft
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
100 changes: 91 additions & 9 deletions src/components/collection-search.tsx
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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<CollectionSearchType>(
collectionSearchLink ? "Server" : "Client"
);
return (
<Stack>
<HStack justify={"space-between"}>
<SegmentGroup.Root
size={"xs"}
value={value}
onValueChange={(e) =>
setValue(e.value as "Text" | "Natural language")
}
onValueChange={(e) => setValue(e.value as CollectionSearchType)}
>
<SegmentGroup.Indicator></SegmentGroup.Indicator>
<SegmentGroup.Items
items={[
{ label: "Text", value: "Text" },
{
label: "Server",
value: "Server",
disabled: !collectionSearchLink,
},
{ label: "Client", value: "Client" },
{
label: "Natural language",
value: "Natural language",
Expand All @@ -51,7 +62,13 @@ export default function CollectionSearch({
/>
</SegmentGroup.Root>
</HStack>
{value === "Text" && (
{value === "Server" && collectionSearchLink && (
<ServerCollectionSearch
setHref={setHref}
link={collectionSearchLink}
></ServerCollectionSearch>
)}
{value === "Client" && (
<CollectionCombobox
collections={collections}
setHref={setHref}
Expand All @@ -68,6 +85,71 @@ export default function CollectionSearch({
);
}

function ServerCollectionSearch({
setHref,
link,
}: {
setHref: (href: string | undefined) => void;
link: StacLink;
}) {
const [value, setValue] = useState("");
const [query, setQuery] = useState<string>();
return (
<Stack>
<form
onSubmit={(e) => {
e.preventDefault();
setQuery(value);
}}
>
<Input
placeholder="Free-text collection search..."
value={value}
onChange={(e) => setValue(e.currentTarget.value)}
/>
</form>

{query && <QueryResults query={query} setHref={setHref} link={link} />}
</Stack>
);
}

function QueryResults({
query,
setHref,
link,
}: {
query: string;
setHref: (href: string | undefined) => void;
link: StacLink;
}) {
const result = useStacCollections(link.href, query);
const [collections, setCollections] = useState<StacCollection[]>();

useEffect(() => {
if (result.data)
setCollections(
result.data.pages.flatMap((page) => page?.collections || [])
);
else setCollections(undefined);
}, [result.data]);

if (result.error)
return (
<Alert.Root status={"error"}>
<Alert.Indicator />
<Alert.Content>
<Alert.Title>Collection search error</Alert.Title>
<Alert.Description>{result.error.toString()}</Alert.Description>
</Alert.Content>
</Alert.Root>
);
else if (collections)
return <Collections collections={collections} setHref={setHref} />;
else if (result.isFetching) return <SkeletonText />;
else return null;
}

function CollectionCombobox({
collections,
setHref,
Expand Down
46 changes: 43 additions & 3 deletions src/components/value.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,13 @@ import {
Button,
ButtonGroup,
Card,
CloseButton,
Dialog,
Heading,
HStack,
Icon,
Image,
Portal,
Span,
Stack,
} from "@chakra-ui/react";
Expand Down Expand Up @@ -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 || [])
Expand Down Expand Up @@ -176,9 +186,36 @@ export function Value({
)}

{!!value.description && (
<Prose>
<MarkdownHooks>{value.description as string}</MarkdownHooks>
</Prose>
<>
<Prose lineClamp={5}>
<MarkdownHooks>{value.description as string}</MarkdownHooks>
</Prose>

<Dialog.Root>
<Dialog.Trigger asChild>
<Button size={"sm"} variant={"outline"}>
View full description
</Button>
</Dialog.Trigger>
<Portal>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.Body>
<Prose>
<MarkdownHooks>
{value.description as string}
</MarkdownHooks>
</Prose>
</Dialog.Body>
<Dialog.CloseTrigger>
<CloseButton size={"sm"} />
</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog.Root>
</>
)}

{selfHref && (
Expand Down Expand Up @@ -309,6 +346,9 @@ export function Value({
collections={collections}
setHref={setHref}
catalogHref={value?.type === "Catalog" ? href : undefined}
collectionSearchLink={
hasFreeTextCollectionSearch && collectionsLink
}
/>
</Section>
)}
Expand Down
5 changes: 5 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
10 changes: 7 additions & 3 deletions src/hooks/stac-collections.ts
Original file line number Diff line number Diff line change
@@ -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) => {
Expand All @@ -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,
Expand Down