mirror of
https://github.com/OpenHands/OpenHands.git
synced 2026-10-07 16:38:34 +08:00
feat: migrate folder browser to /api/file/search_subdirs (#100)
This commit is contained in:
@@ -83,23 +83,23 @@ describe("WorkspaceSelectionForm", () => {
|
||||
|
||||
it("Add Workspaces opens Finder-like modal, navigates, and imports subfolders deduped on repeat", async () => {
|
||||
vi.spyOn(FilesService, "getHome").mockResolvedValue({ home: "/Users/me" });
|
||||
const listSpy = vi
|
||||
.spyOn(FilesService, "listSubdirs")
|
||||
const searchSpy = vi
|
||||
.spyOn(FilesService, "searchSubdirs")
|
||||
.mockImplementation(async (path: string) => {
|
||||
if (path === "/Users/me") {
|
||||
return {
|
||||
path,
|
||||
subdirs: [{ name: "dev", path: "/Users/me/dev" }],
|
||||
items: [{ name: "dev", path: "/Users/me/dev" }],
|
||||
next_page_id: null,
|
||||
};
|
||||
}
|
||||
if (path === "/Users/me/dev") {
|
||||
return {
|
||||
path,
|
||||
subdirs: [
|
||||
items: [
|
||||
{ name: "repo1", path: "/Users/me/dev/repo1" },
|
||||
{ name: "repo2", path: "/Users/me/dev/repo2" },
|
||||
{ name: "repo3", path: "/Users/me/dev/repo3" },
|
||||
],
|
||||
next_page_id: null,
|
||||
};
|
||||
}
|
||||
throw new Error(`unexpected path ${path}`);
|
||||
@@ -141,7 +141,7 @@ describe("WorkspaceSelectionForm", () => {
|
||||
"/Users/me/dev/repo2",
|
||||
"/Users/me/dev/repo3",
|
||||
]);
|
||||
expect(listSpy).toHaveBeenCalledWith("/Users/me/dev");
|
||||
expect(searchSpy).toHaveBeenCalledWith("/Users/me/dev");
|
||||
});
|
||||
|
||||
it("Launch creates a v1 conversation with the selected workspace path as working_dir", async () => {
|
||||
|
||||
@@ -5,20 +5,32 @@ export interface SubdirectoryEntry {
|
||||
path: string;
|
||||
}
|
||||
|
||||
export interface ListSubdirsResponse {
|
||||
path: string;
|
||||
subdirs: SubdirectoryEntry[];
|
||||
export interface SubdirectoryPage {
|
||||
items: SubdirectoryEntry[];
|
||||
next_page_id: string | null;
|
||||
}
|
||||
|
||||
export interface HomeResponse {
|
||||
home: string;
|
||||
}
|
||||
|
||||
export interface SearchSubdirsOptions {
|
||||
pageId?: string | null;
|
||||
limit?: number;
|
||||
}
|
||||
|
||||
const FilesService = {
|
||||
async listSubdirs(path: string): Promise<ListSubdirsResponse> {
|
||||
const response = await createHttpClient().get<ListSubdirsResponse>(
|
||||
"/api/file/list_subdirs",
|
||||
{ params: { path } },
|
||||
async searchSubdirs(
|
||||
path: string,
|
||||
options: SearchSubdirsOptions = {},
|
||||
): Promise<SubdirectoryPage> {
|
||||
const params: Record<string, string | number> = { path };
|
||||
if (options.pageId) params.page_id = options.pageId;
|
||||
if (typeof options.limit === "number") params.limit = options.limit;
|
||||
|
||||
const response = await createHttpClient().get<SubdirectoryPage>(
|
||||
"/api/file/search_subdirs",
|
||||
{ params },
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
@@ -7,8 +7,8 @@ import { I18nKey } from "#/i18n/declaration";
|
||||
import { LocalWorkspace } from "#/types/workspace";
|
||||
import {
|
||||
useHomeDirectory,
|
||||
useListSubdirs,
|
||||
} from "#/hooks/query/use-list-subdirs";
|
||||
useSearchSubdirs,
|
||||
} from "#/hooks/query/use-search-subdirs";
|
||||
import { cn } from "#/utils/utils";
|
||||
import FolderIcon from "#/icons/folder.svg?react";
|
||||
import ChevronLeft from "#/icons/chevron-left-small.svg?react";
|
||||
@@ -122,7 +122,7 @@ export function FolderBrowserModal({
|
||||
isLoading,
|
||||
isError,
|
||||
error,
|
||||
} = useListSubdirs(isOpen ? currentPath : null);
|
||||
} = useSearchSubdirs(isOpen ? currentPath : null);
|
||||
|
||||
const sidebar = useMemo(
|
||||
() => buildSidebar(homeData?.home ?? null),
|
||||
@@ -131,7 +131,7 @@ export function FolderBrowserModal({
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
const subdirs = listing?.subdirs ?? [];
|
||||
const subdirs = listing?.items ?? [];
|
||||
const parent = currentPath ? getParentPath(currentPath) : null;
|
||||
|
||||
const handleUseThisFolder = () => {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import FilesService from "#/api/files-service/files-service.api";
|
||||
|
||||
export const useListSubdirs = (path: string | null) =>
|
||||
export const useSearchSubdirs = (path: string | null) =>
|
||||
useQuery({
|
||||
queryKey: ["file", "list_subdirs", path],
|
||||
queryFn: () => FilesService.listSubdirs(path as string),
|
||||
queryKey: ["file", "search_subdirs", path],
|
||||
queryFn: () => FilesService.searchSubdirs(path as string),
|
||||
enabled: !!path,
|
||||
retry: false,
|
||||
meta: { disableToast: true },
|
||||
Reference in New Issue
Block a user