mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-10-04 09:02:11 +00:00
feat: Update conversation summary and pull request components styling (#607)
* Apply patch [skip ci] * Apply patch [skip ci] * Apply patch [skip ci] * Apply patch [skip ci] * Empty commit to trigger CI * cr --------- Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com> Co-authored-by: bracesproul <braceasproul@gmail.com>
This commit is contained in:
parent
3105a318d2
commit
e92de3f300
2 changed files with 170 additions and 118 deletions
|
|
@ -1,7 +1,9 @@
|
||||||
import { FileText, ChevronDown, ChevronRight } from "lucide-react";
|
import { FileText, ChevronDown, Check } from "lucide-react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { MarkdownText } from "../thread/markdown-text";
|
import { MarkdownText } from "../thread/markdown-text";
|
||||||
import { ToolIconWithTooltip } from "./tool-icon-tooltip";
|
import { cn } from "@/lib/utils";
|
||||||
|
import { Button } from "../ui/button";
|
||||||
|
import { Badge } from "../ui/badge";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ConversationHistorySummary component for rendering conversation history summaries
|
* ConversationHistorySummary component for rendering conversation history summaries
|
||||||
|
|
@ -11,32 +13,59 @@ export function ConversationHistorySummary({ summary }: { summary: string }) {
|
||||||
const [expanded, setExpanded] = useState(true);
|
const [expanded, setExpanded] = useState(true);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="border-border overflow-hidden rounded-md border">
|
<div
|
||||||
<div className="border-b border-blue-300 bg-blue-100/50 p-2 dark:border-blue-800 dark:bg-blue-900/50">
|
className={cn(
|
||||||
<div className="flex items-center justify-between">
|
"group via-background to-background dark:via-background dark:to-background rounded-xl border bg-gradient-to-br from-blue-50/50 transition-shadow dark:from-blue-950/20",
|
||||||
<div className="flex items-center gap-2">
|
"shadow-sm hover:shadow-md",
|
||||||
<ToolIconWithTooltip
|
)}
|
||||||
toolNamePretty="Conversation Summary"
|
>
|
||||||
icon={<FileText className="h-4 w-4" />}
|
{/* Header */}
|
||||||
/>
|
<div
|
||||||
<span className="text-xs font-medium">Conversation Summary</span>
|
className={cn(
|
||||||
</div>
|
"relative flex items-center bg-gradient-to-r from-blue-50 to-blue-50/50 p-4 backdrop-blur-sm dark:from-blue-950/30 dark:to-blue-950/10",
|
||||||
<button
|
"rounded-xl",
|
||||||
onClick={() => setExpanded(!expanded)}
|
)}
|
||||||
className="flex items-center gap-1 text-xs font-normal text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300"
|
>
|
||||||
>
|
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-blue-500 shadow-md dark:bg-blue-600">
|
||||||
{expanded ? (
|
<FileText className="h-4 w-4 text-white" />
|
||||||
<ChevronDown className="h-3 w-3" />
|
|
||||||
) : (
|
|
||||||
<ChevronRight className="h-3 w-3" />
|
|
||||||
)}
|
|
||||||
{expanded ? "Collapse" : "Expand"}
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="ml-3 flex-1">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<h3 className="text-foreground text-sm font-semibold">
|
||||||
|
Conversation Summary
|
||||||
|
</h3>
|
||||||
|
<Badge
|
||||||
|
variant="secondary"
|
||||||
|
className="border-blue-200 bg-blue-100 text-blue-700 dark:border-blue-800 dark:bg-blue-950 dark:text-blue-300"
|
||||||
|
>
|
||||||
|
<Check className="h-3 w-3" />
|
||||||
|
Complete
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
<p className="text-muted-foreground mt-1 text-xs">
|
||||||
|
Summary of the conversation history
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => setExpanded(!expanded)}
|
||||||
|
className="h-8 px-2"
|
||||||
|
>
|
||||||
|
<ChevronDown
|
||||||
|
className={cn(
|
||||||
|
"h-4 w-4 transition-transform duration-200",
|
||||||
|
!expanded && "-rotate-90",
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
{expanded && (
|
{expanded && (
|
||||||
<div className="p-3">
|
<div className="p-4">
|
||||||
<div className="text-sm">
|
<div className="text-sm">
|
||||||
<MarkdownText>{summary}</MarkdownText>
|
<MarkdownText>{summary}</MarkdownText>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -4,19 +4,15 @@ import { useState } from "react";
|
||||||
import {
|
import {
|
||||||
GitPullRequest,
|
GitPullRequest,
|
||||||
Loader2,
|
Loader2,
|
||||||
CheckCircle,
|
|
||||||
ChevronDown,
|
ChevronDown,
|
||||||
ChevronUp,
|
|
||||||
ExternalLink,
|
ExternalLink,
|
||||||
GitPullRequestDraft,
|
GitPullRequestDraft,
|
||||||
|
Clock,
|
||||||
|
Check,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import {
|
import { Button } from "../ui/button";
|
||||||
Tooltip,
|
import { Badge } from "../ui/badge";
|
||||||
TooltipContent,
|
|
||||||
TooltipProvider,
|
|
||||||
TooltipTrigger,
|
|
||||||
} from "../ui/tooltip";
|
|
||||||
|
|
||||||
type PullRequestOpenedProps = {
|
type PullRequestOpenedProps = {
|
||||||
status: "loading" | "generating" | "done";
|
status: "loading" | "generating" | "done";
|
||||||
|
|
@ -41,31 +37,69 @@ export function PullRequestOpened({
|
||||||
}: PullRequestOpenedProps) {
|
}: PullRequestOpenedProps) {
|
||||||
const [expanded, setExpanded] = useState(false);
|
const [expanded, setExpanded] = useState(false);
|
||||||
|
|
||||||
const getStatusIcon = () => {
|
const getStatusBadge = () => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case "loading":
|
case "loading":
|
||||||
return (
|
return (
|
||||||
<div className="h-3.5 w-3.5 rounded-full border border-gray-300 dark:border-gray-600" />
|
<Badge
|
||||||
|
variant="secondary"
|
||||||
|
className="border-purple-200 bg-purple-100 text-purple-700 dark:border-purple-800 dark:bg-purple-950 dark:text-purple-300"
|
||||||
|
>
|
||||||
|
<Clock className="h-3 w-3" />
|
||||||
|
Preparing
|
||||||
|
</Badge>
|
||||||
);
|
);
|
||||||
case "generating":
|
case "generating":
|
||||||
return (
|
return (
|
||||||
<Loader2 className="h-3.5 w-3.5 animate-spin text-gray-500 dark:text-gray-400" />
|
<Badge
|
||||||
|
variant="secondary"
|
||||||
|
className="border-purple-200 bg-purple-100 text-purple-700 dark:border-purple-800 dark:bg-purple-950 dark:text-purple-300"
|
||||||
|
>
|
||||||
|
<Loader2 className="h-3 w-3 animate-spin" />
|
||||||
|
Opening
|
||||||
|
</Badge>
|
||||||
);
|
);
|
||||||
case "done":
|
case "done":
|
||||||
return <CheckCircle className="h-3.5 w-3.5 text-green-500" />;
|
if (isDraft) {
|
||||||
|
return (
|
||||||
|
<Badge
|
||||||
|
variant="secondary"
|
||||||
|
className="border-slate-200 bg-slate-100 text-slate-700 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-300"
|
||||||
|
>
|
||||||
|
<GitPullRequestDraft className="h-3 w-3" />
|
||||||
|
Draft
|
||||||
|
</Badge>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Badge
|
||||||
|
variant="secondary"
|
||||||
|
className="border-emerald-200 bg-emerald-100 text-emerald-700 dark:border-emerald-800 dark:bg-emerald-950 dark:text-emerald-300"
|
||||||
|
>
|
||||||
|
<Check className="h-3 w-3" />
|
||||||
|
Opened
|
||||||
|
</Badge>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStatusText = () => {
|
const getStatusText = () => {
|
||||||
|
if (status === "done" && prNumber && !isDraft) {
|
||||||
|
return `Pull request #${prNumber}`;
|
||||||
|
}
|
||||||
|
return isDraft
|
||||||
|
? `Draft pull request${prNumber ? ` #${prNumber}` : ""}`
|
||||||
|
: `Pull request${prNumber ? ` #${prNumber}` : ""}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getSubtitleText = () => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case "loading":
|
case "loading":
|
||||||
return "Preparing pull request...";
|
return "Preparing to open pull request...";
|
||||||
case "generating":
|
case "generating":
|
||||||
return "Opening pull request...";
|
return "Opening pull request on GitHub...";
|
||||||
case "done":
|
case "done":
|
||||||
return prNumber
|
return branch ? `${branch} → ${targetBranch}` : "Successfully opened";
|
||||||
? `Pull request #${prNumber} opened`
|
|
||||||
: "Pull request opened";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -73,98 +107,87 @@ export function PullRequestOpened({
|
||||||
return status === "done" && description;
|
return status === "done" && description;
|
||||||
};
|
};
|
||||||
|
|
||||||
const iconClassName = "mr-2 h-3.5 w-3.5";
|
|
||||||
|
|
||||||
const getIconWithTooltip = () => {
|
|
||||||
return (
|
|
||||||
<TooltipProvider>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger>
|
|
||||||
{isDraft && (
|
|
||||||
<GitPullRequestDraft
|
|
||||||
className={cn(
|
|
||||||
iconClassName,
|
|
||||||
"text-gray-500 dark:text-gray-400",
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{!isDraft && (
|
|
||||||
<GitPullRequest
|
|
||||||
className={cn(
|
|
||||||
iconClassName,
|
|
||||||
"text-green-500 dark:text-green-400",
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>
|
|
||||||
{isDraft ? "Opened draft pull request" : "Opened pull request"}
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</TooltipProvider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="overflow-hidden rounded-md border border-gray-200 dark:border-gray-700">
|
<div
|
||||||
<div className="flex items-center border-b border-gray-200 bg-gray-50 p-2 dark:border-gray-700 dark:bg-gray-800">
|
className={cn(
|
||||||
{getIconWithTooltip()}
|
"group via-background to-background dark:via-background dark:to-background rounded-xl border bg-gradient-to-br from-purple-50/50 transition-shadow dark:from-purple-950/20",
|
||||||
<div className="flex-1">
|
"shadow-sm hover:shadow-md",
|
||||||
{title && status === "done" && (
|
)}
|
||||||
<div className="mb-0.5 text-xs font-normal text-gray-800 dark:text-gray-200">
|
>
|
||||||
{title}
|
{/* Header */}
|
||||||
</div>
|
<div
|
||||||
)}
|
className={cn(
|
||||||
{branch && status === "done" && (
|
"relative flex items-center bg-gradient-to-r from-purple-50 to-purple-50/50 p-4 backdrop-blur-sm dark:from-purple-950/30 dark:to-purple-950/10",
|
||||||
<div className="text-xs font-normal text-gray-500 dark:text-gray-400">
|
"rounded-xl",
|
||||||
{branch} → {targetBranch}
|
)}
|
||||||
</div>
|
>
|
||||||
)}
|
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-purple-500 shadow-md dark:bg-purple-600">
|
||||||
{!title && (
|
{isDraft ? (
|
||||||
<span className="text-xs font-normal text-gray-800 dark:text-gray-200">
|
<GitPullRequestDraft className="h-4 w-4 text-white" />
|
||||||
{getStatusText()}
|
) : (
|
||||||
</span>
|
<GitPullRequest className="h-4 w-4 text-white" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="ml-3 flex-1">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<h3 className="text-foreground text-sm font-semibold">
|
||||||
|
{title || getStatusText()}
|
||||||
|
</h3>
|
||||||
|
{getStatusBadge()}
|
||||||
|
</div>
|
||||||
|
<p className="text-muted-foreground mt-1 text-xs">
|
||||||
|
{getSubtitleText()}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="text-xs font-normal text-gray-500 dark:text-gray-400">
|
|
||||||
{getStatusText()}
|
|
||||||
</span>
|
|
||||||
{getStatusIcon()}
|
|
||||||
{url && status === "done" && (
|
{url && status === "done" && (
|
||||||
<a
|
<Button
|
||||||
href={url}
|
variant="ghost"
|
||||||
target="_blank"
|
size="sm"
|
||||||
rel="noopener noreferrer"
|
className="h-8 px-2"
|
||||||
className="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"
|
asChild
|
||||||
title="Open pull request"
|
|
||||||
>
|
>
|
||||||
<ExternalLink className="h-3.5 w-3.5" />
|
<a
|
||||||
</a>
|
href={url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
title="Open pull request on GitHub"
|
||||||
|
>
|
||||||
|
<ExternalLink className="h-4 w-4" />
|
||||||
|
</a>
|
||||||
|
</Button>
|
||||||
)}
|
)}
|
||||||
{shouldShowToggle() && (
|
{shouldShowToggle() && (
|
||||||
<button
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
onClick={() => setExpanded(!expanded)}
|
onClick={() => setExpanded(!expanded)}
|
||||||
className="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"
|
className="h-8 px-2"
|
||||||
>
|
>
|
||||||
{expanded ? (
|
<ChevronDown
|
||||||
<ChevronUp className="h-3.5 w-3.5" />
|
className={cn(
|
||||||
) : (
|
"h-4 w-4 transition-transform duration-200",
|
||||||
<ChevronDown className="h-3.5 w-3.5" />
|
!expanded && "-rotate-90",
|
||||||
)}
|
)}
|
||||||
</button>
|
/>
|
||||||
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
{expanded && description && status === "done" && (
|
{expanded && description && status === "done" && (
|
||||||
<div className="border-t border-gray-200 bg-white p-2 dark:border-gray-700 dark:bg-gray-900">
|
<div className="border-t p-4">
|
||||||
<h3 className="mb-1 text-xs font-normal text-gray-500 dark:text-gray-400">
|
<div className="bg-muted/30 rounded-lg p-3">
|
||||||
Description
|
<h4 className="text-muted-foreground mb-2 text-xs font-medium">
|
||||||
</h3>
|
Description
|
||||||
<pre className="text-xs font-normal whitespace-pre-wrap text-gray-800 dark:text-gray-200">
|
</h4>
|
||||||
{description}
|
<pre className="text-foreground text-sm whitespace-pre-wrap">
|
||||||
</pre>
|
{description}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue