From 761a574b091a9d2f2a47da751b4655f10dd1cafd Mon Sep 17 00:00:00 2001 From: Robert Brennan Date: Fri, 3 Jan 2025 15:44:30 -0500 Subject: [PATCH] Small style changes to repo picker (#6013) Co-authored-by: openhands Co-authored-by: Graham Neubig Co-authored-by: sp.wack <83104063+amanape@users.noreply.github.com> --- .../github/github-repo-selector.test.tsx | 9 +- frontend/src/api/github.ts | 7 +- .../features/github/github-repo-selector.tsx | 112 ++++++++++++------ .../github-repositories-suggestion-box.tsx | 22 +--- frontend/src/utils/sanitize-query.ts | 1 + 5 files changed, 84 insertions(+), 67 deletions(-) diff --git a/frontend/__tests__/components/features/github/github-repo-selector.test.tsx b/frontend/__tests__/components/features/github/github-repo-selector.test.tsx index 57bb672993..8d507294d9 100644 --- a/frontend/__tests__/components/features/github/github-repo-selector.test.tsx +++ b/frontend/__tests__/components/features/github/github-repo-selector.test.tsx @@ -14,7 +14,8 @@ describe("GitHubRepositorySelector", () => { , ); @@ -36,7 +37,8 @@ describe("GitHubRepositorySelector", () => { , ); @@ -67,7 +69,8 @@ describe("GitHubRepositorySelector", () => { , ); diff --git a/frontend/src/api/github.ts b/frontend/src/api/github.ts index b2b9697f9b..256968536c 100644 --- a/frontend/src/api/github.ts +++ b/frontend/src/api/github.ts @@ -110,16 +110,11 @@ export const searchPublicRepositories = async ( sort: "" | "updated" | "stars" | "forks" = "stars", order: "desc" | "asc" = "desc", ): Promise => { - const sanitizedQuery = query.trim(); - if (!sanitizedQuery) { - return []; - } - const response = await github.get<{ items: GitHubRepository[] }>( "/search/repositories", { params: { - q: sanitizedQuery, + q: query, per_page, sort, order, diff --git a/frontend/src/components/features/github/github-repo-selector.tsx b/frontend/src/components/features/github/github-repo-selector.tsx index 50f1d5c009..b9f070f213 100644 --- a/frontend/src/components/features/github/github-repo-selector.tsx +++ b/frontend/src/components/features/github/github-repo-selector.tsx @@ -1,46 +1,48 @@ import React from "react"; -import { Autocomplete, AutocompleteItem } from "@nextui-org/react"; +import { + Autocomplete, + AutocompleteItem, + AutocompleteSection, +} from "@nextui-org/react"; import { useDispatch } from "react-redux"; import posthog from "posthog-js"; import { setSelectedRepository } from "#/state/initial-query-slice"; import { useConfig } from "#/hooks/query/use-config"; - -interface GitHubRepositoryWithPublic extends GitHubRepository { - is_public?: boolean; -} +import { sanitizeQuery } from "#/utils/sanitize-query"; interface GitHubRepositorySelectorProps { onInputChange: (value: string) => void; onSelect: () => void; - repositories: GitHubRepositoryWithPublic[]; + userRepositories: GitHubRepository[]; + publicRepositories: GitHubRepository[]; } export function GitHubRepositorySelector({ onInputChange, onSelect, - repositories, + userRepositories, + publicRepositories, }: GitHubRepositorySelectorProps) { const { data: config } = useConfig(); const [selectedKey, setSelectedKey] = React.useState(null); + const allRepositories: GitHubRepository[] = [ + ...publicRepositories.filter( + (repo) => !publicRepositories.find((r) => r.id === repo.id), + ), + ...userRepositories, + ]; + const dispatch = useDispatch(); const handleRepoSelection = (id: string | null) => { - const repo = repositories.find((r) => r.id.toString() === id); - if (!repo) return; - - if (repo.id === -1000) { - window.open( - `https://github.com/apps/${config?.APP_SLUG}/installations/new`, - "_blank", - ); - return; + const repo = allRepositories.find((r) => r.id.toString() === id); + if (repo) { + dispatch(setSelectedRepository(repo.full_name)); + posthog.capture("repository_selected"); + onSelect(); + setSelectedKey(id); } - - dispatch(setSelectedRepository(repo.full_name)); - posthog.capture("repository_selected"); - onSelect(); - setSelectedKey(id); }; const handleClearSelection = () => { @@ -55,8 +57,8 @@ export function GitHubRepositorySelector({ name="repo" aria-label="GitHub Repository" placeholder="Select a GitHub project" + isVirtualized={false} selectedKey={selectedKey} - items={repositories} inputProps={{ classNames: { inputWrapper: @@ -65,27 +67,61 @@ export function GitHubRepositorySelector({ }} onSelectionChange={(id) => handleRepoSelection(id?.toString() ?? null)} onInputChange={onInputChange} - clearButtonProps={{ onPress: handleClearSelection }} + clearButtonProps={{ onClick: handleClearSelection }} listboxProps={{ emptyContent, }} + defaultFilter={(textValue, inputValue) => + !inputValue || + sanitizeQuery(textValue).includes(sanitizeQuery(inputValue)) + } > - {(item) => ( - -
- {item.full_name} - {item.is_public && !!item.stargazers_count && ( - - ({item.stargazers_count}⭐) + {config?.APP_MODE === "saas" && + config?.APP_SLUG && + (( + + e.stopPropagation()} + > + Add more repositories... + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ) as any)} + {userRepositories.length > 0 && ( + + {userRepositories.map((repo) => ( + + {repo.full_name} + + ))} + + )} + {publicRepositories.length > 0 && ( + + {publicRepositories.map((repo) => ( + + {repo.full_name} + + ({repo.stargazers_count || 0}⭐) - )} -
-
+ + ))} + )} ); diff --git a/frontend/src/components/features/github/github-repositories-suggestion-box.tsx b/frontend/src/components/features/github/github-repositories-suggestion-box.tsx index b6420f6336..3ad3f65a21 100644 --- a/frontend/src/components/features/github/github-repositories-suggestion-box.tsx +++ b/frontend/src/components/features/github/github-repositories-suggestion-box.tsx @@ -11,7 +11,6 @@ import { useSearchRepositories } from "#/hooks/query/use-search-repositories"; import { useUserRepositories } from "#/hooks/query/use-user-repositories"; import { sanitizeQuery } from "#/utils/sanitize-query"; import { useDebounce } from "#/hooks/use-debounce"; -import { useConfig } from "#/hooks/query/use-config"; interface GitHubRepositoriesSuggestionBoxProps { handleSubmit: () => void; @@ -29,7 +28,6 @@ export function GitHubRepositoriesSuggestionBox({ const [searchQuery, setSearchQuery] = React.useState(""); const debouncedSearchQuery = useDebounce(searchQuery, 300); - const { data: config } = useConfig(); // TODO: Use `useQueries` to fetch all repositories in parallel const { data: appRepositories } = useAppRepositories(); const { data: userRepositories } = useUserRepositories(); @@ -37,19 +35,6 @@ export function GitHubRepositoriesSuggestionBox({ sanitizeQuery(debouncedSearchQuery), ); - const saasPlaceholderRepository = React.useMemo(() => { - if (config?.APP_MODE === "saas" && config?.APP_SLUG) { - return [ - { - id: -1000, - full_name: "Add more repositories...", - }, - ]; - } - - return []; - }, [config]); - const repositories = userRepositories?.pages.flatMap((page) => page.data) || appRepositories?.pages.flatMap((page) => page.data) || @@ -74,11 +59,8 @@ export function GitHubRepositoriesSuggestionBox({ ) : ( query + .trim() .replace(/https?:\/\//, "") .replace(/github.com\//, "") .replace(/\.git$/, "")