Files
sim/apps/sim/components/ui/copy-code-button.tsx
Waleed d0d35dd406 fix: address PR review comments (#4042)
* fix: address PR review comments on staging release

- Add try/catch around clipboard.writeText() in CopyCodeButton
- Add missing folder and past_chat cases in resolveResourceFromContext
- Return 400 for ZodError instead of 500 in all 8 Athena API routes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(api): return 400 for Zod validation errors across 27 API routes

Routes using z.parse() were returning 500 for ZodError (client input
validation failures). Added instanceof z.ZodError check to return 400
before the generic 500 handler, matching the established pattern used
by 115+ other routes.

Affected services: CloudWatch (7), CloudFormation (7), DynamoDB (6),
Slack (3), Outlook (2), OneDrive (1), Google Drive (1).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(api): add success:false to ZodError responses for consistency

7 routes used { success: false, error: ... } in their generic error
handler but our ZodError handler only returned { error: ... }. Aligned
the ZodError response shape to match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 00:26:33 -07:00

47 lines
1.2 KiB
TypeScript

'use client'
import { useCallback, useEffect, useRef, useState } from 'react'
import { Check, Copy } from '@/components/emcn'
import { cn } from '@/lib/core/utils/cn'
interface CopyCodeButtonProps {
code: string
className?: string
}
export function CopyCodeButton({ code, className }: CopyCodeButtonProps) {
const [copied, setCopied] = useState(false)
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
const handleCopy = useCallback(async () => {
try {
await navigator.clipboard.writeText(code)
setCopied(true)
if (timerRef.current) clearTimeout(timerRef.current)
timerRef.current = setTimeout(() => setCopied(false), 2000)
} catch {
// Clipboard write can fail when document lacks focus or permission is denied
}
}, [code])
useEffect(
() => () => {
if (timerRef.current) clearTimeout(timerRef.current)
},
[]
)
return (
<button
type='button'
onClick={handleCopy}
className={cn(
'flex items-center gap-1 rounded px-1.5 py-0.5 text-xs transition-colors',
className
)}
>
{copied ? <Check className='size-3.5' /> : <Copy className='size-3.5' />}
</button>
)
}