mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-01 02:02:20 +00:00
fix(ui): address greptile feedback on coding-agent prompt modal
- Switch logo paths from '../ui/assets/logos/' relative form to absolute '/ui/assets/logos/' so they don't break on routes whose '..' traversal lands somewhere other than the UI root (matches the convention already used in MCPLogoSelector.tsx). - Split the 'copied' state between the small icon copy button and the primary 'Copy Virtual Key' button. Clicking the icon used to flip the primary button's label to 'Copied!' even though the user never touched it, which is confusing. - Add tests that pin both behaviors (logos use absolute paths; icon click does not relabel the primary button) so future regressions fail the suite. Co-authored-by: ishaan-berri <ishaan-berri@users.noreply.github.com>
This commit is contained in:
parent
99ad65f2a2
commit
1c9d66eacd
2 changed files with 38 additions and 12 deletions
|
|
@ -104,4 +104,23 @@ describe("CreatedKeyDisplay", () => {
|
|||
|
||||
expect(screen.getByRole("button", { name: /copy virtual key/i })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("does not relabel the primary button when the icon copy button is clicked", async () => {
|
||||
const user = userEvent.setup({ advanceTimers: vi.advanceTimersByTime });
|
||||
render(<CreatedKeyDisplay apiKey="sk-test-123" />);
|
||||
|
||||
await user.click(screen.getByRole("button", { name: /^copy api key$/i }));
|
||||
|
||||
expect(screen.getByRole("button", { name: /copy virtual key/i })).toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: /^copied!$/i })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("uses absolute /ui/assets/logos/ paths so logos resolve regardless of the current route", () => {
|
||||
render(<CreatedKeyDisplay apiKey="sk-test-123" />);
|
||||
const images = screen.getByTestId("coding-agent-logos").querySelectorAll("img");
|
||||
|
||||
Array.from(images).forEach((img) => {
|
||||
expect(img.getAttribute("src")).toMatch(/^\/ui\/assets\/logos\//);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ interface CreatedKeyDisplayProps {
|
|||
}
|
||||
|
||||
const codingAgentLogos: { name: string; src: string }[] = [
|
||||
{ name: "Cursor", src: "../ui/assets/logos/cursor.svg" },
|
||||
{ name: "Claude Code", src: "../ui/assets/logos/anthropic.svg" },
|
||||
{ name: "OpenAI Codex", src: "../ui/assets/logos/openai_small.svg" },
|
||||
{ name: "GitHub Copilot", src: "../ui/assets/logos/github_copilot.svg" },
|
||||
{ name: "Cursor", src: "/ui/assets/logos/cursor.svg" },
|
||||
{ name: "Claude Code", src: "/ui/assets/logos/anthropic.svg" },
|
||||
{ name: "OpenAI Codex", src: "/ui/assets/logos/openai_small.svg" },
|
||||
{ name: "GitHub Copilot", src: "/ui/assets/logos/github_copilot.svg" },
|
||||
];
|
||||
|
||||
const CodingAgentLogos: React.FC = () => (
|
||||
|
|
@ -70,15 +70,22 @@ const resolveProxyBaseUrl = (): string => {
|
|||
};
|
||||
|
||||
const CreatedKeyDisplay: React.FC<CreatedKeyDisplayProps> = ({ apiKey }) => {
|
||||
const [copiedKey, setCopiedKey] = useState(false);
|
||||
const [copiedKeyIcon, setCopiedKeyIcon] = useState(false);
|
||||
const [copiedKeyButton, setCopiedKeyButton] = useState(false);
|
||||
const [copiedPrompt, setCopiedPrompt] = useState(false);
|
||||
|
||||
const codingAgentPrompt = useMemo(() => buildCodingAgentPrompt(resolveProxyBaseUrl()), []);
|
||||
|
||||
const handleCopyKey = () => {
|
||||
setCopiedKey(true);
|
||||
const handleCopyKeyIcon = () => {
|
||||
setCopiedKeyIcon(true);
|
||||
MessageManager.success("Key copied to clipboard");
|
||||
setTimeout(() => setCopiedKey(false), 2000);
|
||||
setTimeout(() => setCopiedKeyIcon(false), 2000);
|
||||
};
|
||||
|
||||
const handleCopyKeyButton = () => {
|
||||
setCopiedKeyButton(true);
|
||||
MessageManager.success("Key copied to clipboard");
|
||||
setTimeout(() => setCopiedKeyButton(false), 2000);
|
||||
};
|
||||
|
||||
const handleCopyPrompt = () => {
|
||||
|
|
@ -110,8 +117,8 @@ const CreatedKeyDisplay: React.FC<CreatedKeyDisplayProps> = ({ apiKey }) => {
|
|||
<div className="rounded-md border mb-4" style={{ borderColor: "#e5e7eb", background: "#fafafa" }}>
|
||||
<div className="flex items-center justify-between px-3 pt-3 pb-1">
|
||||
<span className="text-sm font-medium text-gray-700">Your API Key</span>
|
||||
<Tooltip title={copiedKey ? "Copied!" : "Copy API key"}>
|
||||
<CopyToClipboard text={apiKey} onCopy={handleCopyKey}>
|
||||
<Tooltip title={copiedKeyIcon ? "Copied!" : "Copy API key"}>
|
||||
<CopyToClipboard text={apiKey} onCopy={handleCopyKeyIcon}>
|
||||
<Button type="text" size="small" aria-label="Copy API key" icon={<CopyOutlined />} />
|
||||
</CopyToClipboard>
|
||||
</Tooltip>
|
||||
|
|
@ -162,9 +169,9 @@ const CreatedKeyDisplay: React.FC<CreatedKeyDisplayProps> = ({ apiKey }) => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<CopyToClipboard text={apiKey} onCopy={handleCopyKey}>
|
||||
<CopyToClipboard text={apiKey} onCopy={handleCopyKeyButton}>
|
||||
<Button type="primary" style={{ marginTop: 16 }}>
|
||||
{copiedKey ? "Copied!" : "Copy Virtual Key"}
|
||||
{copiedKeyButton ? "Copied!" : "Copy Virtual Key"}
|
||||
</Button>
|
||||
</CopyToClipboard>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue