mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-09-30 12:43:16 +00:00
parent
46b435a543
commit
c70da1b1c2
2 changed files with 106 additions and 20 deletions
|
|
@ -31,10 +31,22 @@ type FilterStatus =
|
|||
|
||||
function AllThreadsPageContent() {
|
||||
const router = useRouter();
|
||||
const limit = 25;
|
||||
const [offset, setOffset] = useState(0);
|
||||
const { currentInstallation, installationsLoading } = useGitHubAppProvider();
|
||||
const { threads, isLoading: threadsLoading } = useThreadsSWR({
|
||||
const {
|
||||
threads,
|
||||
isLoading: threadsLoading,
|
||||
hasMore,
|
||||
} = useThreadsSWR({
|
||||
assistantId: MANAGER_GRAPH_ID,
|
||||
currentInstallation,
|
||||
pagination: {
|
||||
limit,
|
||||
offset,
|
||||
sortBy: "updated_at",
|
||||
sortOrder: "desc",
|
||||
},
|
||||
});
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [statusFilter, setStatusFilter] = useState<FilterStatus>("all");
|
||||
|
|
@ -96,6 +108,11 @@ function AllThreadsPageContent() {
|
|||
(statusFilter === "all"
|
||||
? Object.values(groupedThreads).flat().length === 0
|
||||
: filteredThreads.length === 0);
|
||||
const showNoThreads =
|
||||
filteredThreads.length === 0 &&
|
||||
!threadsLoading &&
|
||||
!statusLoading &&
|
||||
!showThreadsLoading;
|
||||
|
||||
return (
|
||||
<div className="bg-background flex h-screen flex-col">
|
||||
|
|
@ -233,22 +250,18 @@ function AllThreadsPageContent() {
|
|||
</div>
|
||||
)}
|
||||
|
||||
{filteredThreads.length === 0 &&
|
||||
!threadsLoading &&
|
||||
!statusLoading && (
|
||||
<div className="py-12 text-center">
|
||||
<div className="text-muted-foreground mb-2">
|
||||
No threads found
|
||||
</div>
|
||||
<div className="text-muted-foreground/70 text-xs">
|
||||
{!threads || threads.length === 0
|
||||
? "No threads have been created yet"
|
||||
: searchQuery
|
||||
? "Try adjusting your search query"
|
||||
: "No threads match the selected filter"}
|
||||
</div>
|
||||
{showNoThreads && (
|
||||
<div className="py-12 text-center">
|
||||
<div className="text-muted-foreground mb-2">No threads found</div>
|
||||
<div className="text-muted-foreground/70 text-xs">
|
||||
{!threads || threads.length === 0
|
||||
? "No threads have been created yet"
|
||||
: searchQuery
|
||||
? "Try adjusting your search query"
|
||||
: "No threads match the selected filter"}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{showThreadsLoading && (
|
||||
<div>
|
||||
|
|
@ -264,6 +277,16 @@ function AllThreadsPageContent() {
|
|||
</div>
|
||||
</div>
|
||||
)}
|
||||
{!showNoThreads && hasMore && (
|
||||
<div className="flex items-center justify-center">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setOffset((prev) => prev + limit)}
|
||||
>
|
||||
Load more
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@ import { ManagerGraphState } from "@open-swe/shared/open-swe/manager/types";
|
|||
import { PlannerGraphState } from "@open-swe/shared/open-swe/planner/types";
|
||||
import { ReviewerGraphState } from "@open-swe/shared/open-swe/reviewer/types";
|
||||
import { GraphState } from "@open-swe/shared/open-swe/types";
|
||||
import { useMemo } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
import type { Installation } from "./useGitHubInstallations";
|
||||
|
||||
type ThreadSortBy = "thread_id" | "status" | "created_at" | "updated_at";
|
||||
type SortOrder = "asc" | "desc";
|
||||
/**
|
||||
* Union type representing all possible graph states in the Open SWE system
|
||||
*/
|
||||
|
|
@ -25,6 +27,32 @@ interface UseThreadsSWROptions {
|
|||
revalidateOnReconnect?: boolean;
|
||||
currentInstallation?: Installation | null;
|
||||
disableOrgFiltering?: boolean;
|
||||
/**
|
||||
* Pagination options
|
||||
*/
|
||||
pagination?: {
|
||||
/**
|
||||
* Maximum number of threads to return.
|
||||
* @default 25
|
||||
*/
|
||||
limit?: number;
|
||||
/**
|
||||
* Offset to start from.
|
||||
* @default 0
|
||||
*/
|
||||
offset?: number;
|
||||
/**
|
||||
* Sort by.
|
||||
* @default "updated_at"
|
||||
*/
|
||||
sortBy?: ThreadSortBy;
|
||||
/**
|
||||
* Sort order.
|
||||
* Must be one of 'asc' or 'desc'.
|
||||
* @default "desc"
|
||||
*/
|
||||
sortOrder?: SortOrder;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -45,12 +73,34 @@ export function useThreadsSWR<
|
|||
revalidateOnReconnect = THREAD_SWR_CONFIG.revalidateOnReconnect,
|
||||
currentInstallation,
|
||||
disableOrgFiltering,
|
||||
pagination,
|
||||
} = options;
|
||||
const [hasMoreState, setHasMoreState] = useState(true);
|
||||
|
||||
const paginationWithDefaults = {
|
||||
limit: 25,
|
||||
offset: 0,
|
||||
sortBy: "updated_at" as ThreadSortBy,
|
||||
sortOrder: "desc" as SortOrder,
|
||||
...pagination,
|
||||
};
|
||||
|
||||
const apiUrl: string | undefined = process.env.NEXT_PUBLIC_API_URL ?? "";
|
||||
|
||||
// Create a unique key for SWR caching based on assistantId
|
||||
const swrKey = assistantId ? ["threads", assistantId] : ["threads", "all"];
|
||||
// Create a unique key for SWR caching based on assistantId and pagination parameters
|
||||
const swrKey = useMemo(() => {
|
||||
const baseKey = assistantId ? ["threads", assistantId] : ["threads", "all"];
|
||||
if (pagination) {
|
||||
return [
|
||||
...baseKey,
|
||||
paginationWithDefaults.limit,
|
||||
paginationWithDefaults.offset,
|
||||
paginationWithDefaults.sortBy,
|
||||
paginationWithDefaults.sortOrder,
|
||||
];
|
||||
}
|
||||
return baseKey;
|
||||
}, [assistantId, paginationWithDefaults]);
|
||||
|
||||
const fetcher = async (): Promise<Thread<TGraphState>[]> => {
|
||||
if (!apiUrl) {
|
||||
|
|
@ -63,8 +113,11 @@ export function useThreadsSWR<
|
|||
metadata: {
|
||||
graph_id: assistantId,
|
||||
},
|
||||
...(paginationWithDefaults ? paginationWithDefaults : {}),
|
||||
}
|
||||
: undefined;
|
||||
: paginationWithDefaults
|
||||
? paginationWithDefaults
|
||||
: undefined;
|
||||
|
||||
return await client.threads.search<TGraphState>(searchArgs);
|
||||
};
|
||||
|
|
@ -89,7 +142,12 @@ export function useThreadsSWR<
|
|||
return allThreads;
|
||||
}
|
||||
|
||||
if (!allThreads.length) {
|
||||
setHasMoreState(false);
|
||||
}
|
||||
|
||||
if (!currentInstallation) {
|
||||
setHasMoreState(false);
|
||||
return [];
|
||||
}
|
||||
|
||||
|
|
@ -102,11 +160,16 @@ export function useThreadsSWR<
|
|||
});
|
||||
}, [data, currentInstallation, disableOrgFiltering]);
|
||||
|
||||
const hasMore = useMemo(() => {
|
||||
return hasMoreState && !!threads.length;
|
||||
}, [threads, paginationWithDefaults]);
|
||||
|
||||
return {
|
||||
threads,
|
||||
error,
|
||||
isLoading,
|
||||
isValidating,
|
||||
mutate,
|
||||
hasMore,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue