Skip to content

feat(logs): add copy button to AI log analysis result#4330

Open
alirizatuncer wants to merge 1 commit intoDokploy:canaryfrom
alirizatuncer:feat/copy-ai-log-analysis
Open

feat(logs): add copy button to AI log analysis result#4330
alirizatuncer wants to merge 1 commit intoDokploy:canaryfrom
alirizatuncer:feat/copy-ai-log-analysis

Conversation

@alirizatuncer
Copy link
Copy Markdown

@alirizatuncer alirizatuncer commented Apr 29, 2026

Summary

The AI Log Analysis popover renders the AI response as Markdown but provides no
way to copy it. This adds a one-click Copy button to the result action row that
copies the raw Markdown to the clipboard. Same change covers both call sites
(Deployments view and container Logs view) since they share the
AnalyzeLogs component.

Changes

  • apps/dokploy/components/dashboard/docker/logs/analyze-logs.tsx
    • Add Copy and Check icons to the lucide-react import.
    • Track a copied boolean state.
    • handleCopy writes data.analysis to the clipboard, flips the icon
      to Check for 2s, falls back to a sonner error toast if the
      clipboard API rejects.
    • New icon-only Button placed between Re-analyze and the
      provider-reset X.

Test plan

  • Build context (Deployments → View → AI → Analyze → Copy) — Markdown
    preserved when pasted.
  • Runtime context (Logs tab → container AI button) — same.
  • Light + dark mode visual check.
  • Clipboard rejection path shows a "Failed to copy to clipboard" toast.
  • pnpm lint + pnpm typecheck clean.

Notes

Mirrors the existing copy-button pattern already used in
show-deployment.tsx.

Greptile Summary

Adds a Copy button to the AnalyzeLogs popover so users can copy the raw Markdown analysis to the clipboard. The implementation is clean and follows the existing pattern in the codebase — the button is correctly scoped to the data?.analysis branch, uses a 2-second visual confirmation state, and provides a fallback error toast. Two minor P2 items: the icon-only button uses title but is missing aria-label for screen-reader accessibility, and the setTimeout handle is not cleared on unmount.

Confidence Score: 4/5

Safe to merge — only P2 style/accessibility findings, no logic or security issues.

All findings are P2 (missing aria-label, uncleared setTimeout). The core logic is correct, the button is properly conditionally rendered, and the clipboard API usage is standard.

No files require special attention beyond the two P2 suggestions in analyze-logs.tsx.

Reviews (1): Last reviewed commit: "feat(logs): add copy button to AI log an..." | Re-trigger Greptile

Greptile also left 2 inline comments on this PR.

@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. enhancement New feature or request labels Apr 29, 2026
Comment on lines +191 to +202
<Button
size="sm"
variant="outline"
onClick={handleCopy}
title="Copy analysis"
>
{copied ? (
<Check className="h-3.5 w-3.5" />
) : (
<Copy className="h-3.5 w-3.5" />
)}
</Button>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing aria-label on icon-only button

The button contains only an icon with no visible text label. The title attribute provides a tooltip for sighted users but is not reliably exposed to screen readers. Adding aria-label ensures assistive technologies announce the button's purpose.

Suggested change
<Button
size="sm"
variant="outline"
onClick={handleCopy}
title="Copy analysis"
>
{copied ? (
<Check className="h-3.5 w-3.5" />
) : (
<Copy className="h-3.5 w-3.5" />
)}
</Button>
<Button
size="sm"
variant="outline"
onClick={handleCopy}
title="Copy analysis"
aria-label="Copy analysis"
>

try {
await navigator.clipboard.writeText(data.analysis);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 setTimeout not cleaned up on unmount

If the popover is closed before the 2-second window expires, the pending timeout still fires and calls setCopied. While React 18 no longer warns about this, storing the timer ref and clearing it on unmount is the idiomatic approach and avoids the stale state update.

@berkay-digital
Copy link
Copy Markdown

Duplicate of #4294

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants