diff --git a/ui/src/pages/IssueDetail.tsx b/ui/src/pages/IssueDetail.tsx index 0eecd014..8e6c206a 100644 --- a/ui/src/pages/IssueDetail.tsx +++ b/ui/src/pages/IssueDetail.tsx @@ -9,6 +9,7 @@ import { authApi } from "../api/auth"; import { projectsApi } from "../api/projects"; import { useCompany } from "../context/CompanyContext"; import { usePanel } from "../context/PanelContext"; +import { useToast } from "../context/ToastContext"; import { useBreadcrumbs } from "../context/BreadcrumbContext"; import { queryKeys } from "../lib/queryKeys"; import { readIssueDetailBreadcrumb } from "../lib/issueDetailBreadcrumb"; @@ -36,8 +37,10 @@ import { ScrollArea } from "@/components/ui/scroll-area"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Activity as ActivityIcon, + Check, ChevronDown, ChevronRight, + Copy, EyeOff, Hexagon, ListTree, @@ -196,7 +199,9 @@ export function IssueDetail() { const queryClient = useQueryClient(); const navigate = useNavigate(); const location = useLocation(); + const { pushToast } = useToast(); const [moreOpen, setMoreOpen] = useState(false); + const [copied, setCopied] = useState(false); const [mobilePropsOpen, setMobilePropsOpen] = useState(false); const [detailTab, setDetailTab] = useState("comments"); const [secondaryOpen, setSecondaryOpen] = useState({ @@ -585,6 +590,15 @@ export function IssueDetail() { return () => closePanel(); }, [issue]); // eslint-disable-line react-hooks/exhaustive-deps + const copyIssueToClipboard = async () => { + if (!issue) return; + const md = `# ${issue.identifier}: ${issue.title}\n\n${issue.description ?? ""}`; + await navigator.clipboard.writeText(md); + setCopied(true); + pushToast({ title: "Copied to clipboard", tone: "success" }); + setTimeout(() => setCopied(false), 2000); + }; + if (isLoading) return

Loading...

; if (error) return

{error.message}

; if (!issue) return null; @@ -737,17 +751,34 @@ export function IssueDetail() { )} - +
+ + +
+