mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-10-05 09:32:14 +00:00
feat: Implement a loading and empty state for recent & running threads (#257)
* feat: Implement a loading and empty state for recent & running threads * cr
This commit is contained in:
parent
3cd44ed86b
commit
a93614ffa6
3 changed files with 69 additions and 12 deletions
|
|
@ -9,7 +9,7 @@ import { Toaster } from "@/components/ui/sonner";
|
||||||
import { Suspense } from "react";
|
import { Suspense } from "react";
|
||||||
|
|
||||||
export default function ChatPage() {
|
export default function ChatPage() {
|
||||||
const { threads } = useThreads<GraphState>(
|
const { threads, threadsLoading } = useThreads<GraphState>(
|
||||||
process.env.NEXT_PUBLIC_MANAGER_ASSISTANT_ID,
|
process.env.NEXT_PUBLIC_MANAGER_ASSISTANT_ID,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -22,7 +22,10 @@ export default function ChatPage() {
|
||||||
<Suspense>
|
<Suspense>
|
||||||
<Toaster />
|
<Toaster />
|
||||||
<GitHubAppProvider>
|
<GitHubAppProvider>
|
||||||
<DefaultView threads={displayThreads} />
|
<DefaultView
|
||||||
|
threads={displayThreads}
|
||||||
|
threadsLoading={threadsLoading}
|
||||||
|
/>
|
||||||
</GitHubAppProvider>
|
</GitHubAppProvider>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import {
|
||||||
GitPullRequest,
|
GitPullRequest,
|
||||||
Bug,
|
Bug,
|
||||||
FilePlus2,
|
FilePlus2,
|
||||||
|
Archive,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { ThreadDisplayInfo } from "./types";
|
import { ThreadDisplayInfo } from "./types";
|
||||||
|
|
@ -33,13 +34,14 @@ import { Label } from "../ui/label";
|
||||||
import { ContentBlocksPreview } from "../thread/ContentBlocksPreview";
|
import { ContentBlocksPreview } from "../thread/ContentBlocksPreview";
|
||||||
import { TooltipIconButton } from "../ui/tooltip-icon-button";
|
import { TooltipIconButton } from "../ui/tooltip-icon-button";
|
||||||
import { ThemeToggle } from "../theme-toggle";
|
import { ThemeToggle } from "../theme-toggle";
|
||||||
import { ThreadCard } from "./thread-card";
|
import { ThreadCard, ThreadCardLoading } from "./thread-card";
|
||||||
|
|
||||||
interface DefaultViewProps {
|
interface DefaultViewProps {
|
||||||
threads: ThreadDisplayInfo[];
|
threads: ThreadDisplayInfo[];
|
||||||
|
threadsLoading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DefaultView({ threads }: DefaultViewProps) {
|
export function DefaultView({ threads, threadsLoading }: DefaultViewProps) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const apiUrl: string | undefined = process.env.NEXT_PUBLIC_API_URL ?? "";
|
const apiUrl: string | undefined = process.env.NEXT_PUBLIC_API_URL ?? "";
|
||||||
const assistantId: string | undefined =
|
const assistantId: string | undefined =
|
||||||
|
|
@ -149,14 +151,31 @@ export function DefaultView({ threads }: DefaultViewProps) {
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid gap-3 md:grid-cols-2">
|
{threadsLoading || threads.length ? (
|
||||||
{threads.slice(0, 4).map((thread) => (
|
<div className="grid gap-3 md:grid-cols-2">
|
||||||
<ThreadCard
|
{threadsLoading && threads.length === 0 && (
|
||||||
key={thread.id}
|
<>
|
||||||
thread={thread}
|
<ThreadCardLoading />
|
||||||
/>
|
<ThreadCardLoading />
|
||||||
))}
|
<ThreadCardLoading />
|
||||||
</div>
|
<ThreadCardLoading />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{threads.slice(0, 4).map((thread) => (
|
||||||
|
<ThreadCard
|
||||||
|
key={thread.id}
|
||||||
|
thread={thread}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="flex items-center justify-center py-8">
|
||||||
|
<span className="text-muted-foreground flex items-center gap-2">
|
||||||
|
<Archive className="size-4" />
|
||||||
|
<span className="text-sm">No threads found</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Quick Actions */}
|
{/* Quick Actions */}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import { ThreadDisplayInfo } from "./types";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { Badge } from "../ui/badge";
|
import { Badge } from "../ui/badge";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
|
import { Skeleton } from "../ui/skeleton";
|
||||||
|
|
||||||
export function ThreadCard({ thread }: { thread: ThreadDisplayInfo }) {
|
export function ThreadCard({ thread }: { thread: ThreadDisplayInfo }) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
@ -136,3 +137,37 @@ export function ThreadCard({ thread }: { thread: ThreadDisplayInfo }) {
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function ThreadCardLoading() {
|
||||||
|
return (
|
||||||
|
<Card className="border-border bg-card px-0 py-3 dark:bg-gray-950">
|
||||||
|
<CardHeader>
|
||||||
|
<div className="flex items-start justify-between">
|
||||||
|
<div className="min-w-0 flex-1">
|
||||||
|
<CardTitle className="text-foreground truncate text-sm font-medium">
|
||||||
|
<Skeleton className="h-5 w-48" />
|
||||||
|
</CardTitle>
|
||||||
|
<div className="mt-1 flex items-center gap-1">
|
||||||
|
<Skeleton className="h-3 w-3 rounded-full" />
|
||||||
|
<Skeleton className="h-3 w-32" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Skeleton className="h-6 w-24 rounded-full" />
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Skeleton className="h-3 w-16" />
|
||||||
|
<Skeleton className="h-3 w-1" />
|
||||||
|
<Skeleton className="h-3 w-24" />
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<Skeleton className="h-5 w-5 rounded-full" />
|
||||||
|
<Skeleton className="h-5 w-5 rounded-full" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue