Skip to content

Commit d46a92c

Browse files
authored
feat(inbox): add copy-link button to pull request detail (#2692)
1 parent 6c091ec commit d46a92c

4 files changed

Lines changed: 36 additions & 26 deletions

File tree

packages/ui/src/features/inbox/components/AgentRunDetail.tsx

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import {
1313
parsePrUrl,
1414
} from "@posthog/core/inbox/reportPresentation";
1515
import { Button } from "@posthog/quill";
16-
import { buildInboxDeeplink } from "@posthog/shared/deeplink";
1716
import {
1817
isTerminalStatus,
1918
type SignalReport,
@@ -49,13 +48,13 @@ import {
4948
} from "@posthog/ui/features/inbox/components/utils/source-product-icons";
5049
import { useInboxReportSignals } from "@posthog/ui/features/inbox/hooks/useInboxReports";
5150
import { useReportTasks } from "@posthog/ui/features/inbox/hooks/useReportTasks";
51+
import { copyInboxReportLink } from "@posthog/ui/features/inbox/utils/copyInboxReportLink";
5252
import { TaskLogsPanel } from "@posthog/ui/features/task-detail/components/TaskLogsPanel";
5353
import { RelativeTimestamp } from "@posthog/ui/primitives/RelativeTimestamp";
5454
import { openTask } from "@posthog/ui/router/useOpenTask";
5555
import { DropdownMenu, Flex, Text } from "@radix-ui/themes";
5656
import { Link } from "@tanstack/react-router";
5757
import { useMemo, useState } from "react";
58-
import { toast } from "sonner";
5958

6059
export function TaskRunStatusDot({ status }: { status: TaskRunStatus }) {
6160
const terminal = isTerminalStatus(status);
@@ -277,16 +276,6 @@ function AgentRunDetailContent({ report }: { report: SignalReport }) {
277276
return hasInFlight && hasPriorTerminal;
278277
}, [reportTasks]);
279278

280-
const handleCopyLink = () => {
281-
const url = buildInboxDeeplink(report.id, report.title, {
282-
isDevBuild: import.meta.env.DEV,
283-
});
284-
navigator.clipboard
285-
.writeText(url)
286-
.then(() => toast.success("Link copied"))
287-
.catch(() => toast.error("Couldn't copy link"));
288-
};
289-
290279
return (
291280
<Flex direction="column" className="min-h-full">
292281
<InboxDetailPageHeader
@@ -371,7 +360,7 @@ function AgentRunDetailContent({ report }: { report: SignalReport }) {
371360
type="button"
372361
variant="outline"
373362
size="sm"
374-
onClick={handleCopyLink}
363+
onClick={() => copyInboxReportLink(report)}
375364
title="Copy a deep link to this run"
376365
>
377366
<CopyIcon size={12} />

packages/ui/src/features/inbox/components/PullRequestDetail.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
ArrowSquareOutIcon,
3+
CopyIcon,
34
GitPullRequestIcon,
45
MagnifyingGlassIcon,
56
} from "@phosphor-icons/react";
@@ -13,6 +14,7 @@ import { PrDiffStats } from "@posthog/ui/features/inbox/components/PrDiffStats";
1314
import { ReportDetailActions } from "@posthog/ui/features/inbox/components/ReportDetailActions";
1415
import { ReportTasksSection } from "@posthog/ui/features/inbox/components/ReportTasksSection";
1516
import { SuggestedReviewersSection } from "@posthog/ui/features/inbox/components/SuggestedReviewersSection";
17+
import { copyInboxReportLink } from "@posthog/ui/features/inbox/utils/copyInboxReportLink";
1618
import { Text } from "@radix-ui/themes";
1719

1820
interface PullRequestDetailProps {
@@ -72,6 +74,15 @@ function PullRequestDetailContent({ report }: { report: SignalReport }) {
7274
primaryAction={
7375
<>
7476
<ReportDetailActions report={report} />
77+
<Button
78+
type="button"
79+
variant="outline"
80+
size="sm"
81+
onClick={() => copyInboxReportLink(report)}
82+
title="Copy a deep link to this report"
83+
>
84+
<CopyIcon size={12} />
85+
</Button>
7586
{prRef && report.implementation_pr_url ? (
7687
<Button
7788
type="button"

packages/ui/src/features/inbox/components/ReportDetail.tsx

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,13 @@ import {
44
MagnifyingGlassIcon,
55
} from "@phosphor-icons/react";
66
import { Button } from "@posthog/quill";
7-
import { buildInboxDeeplink } from "@posthog/shared/deeplink";
87
import type { SignalReport } from "@posthog/shared/types";
98
import { InboxDetailFrame } from "@posthog/ui/features/inbox/components/InboxDetailFrame";
109
import { InboxReportDetailGate } from "@posthog/ui/features/inbox/components/InboxReportDetailGate";
1110
import { ReportDetailActions } from "@posthog/ui/features/inbox/components/ReportDetailActions";
1211
import { ReportTasksSection } from "@posthog/ui/features/inbox/components/ReportTasksSection";
1312
import { SuggestedReviewersSection } from "@posthog/ui/features/inbox/components/SuggestedReviewersSection";
14-
import { toast } from "sonner";
13+
import { copyInboxReportLink } from "@posthog/ui/features/inbox/utils/copyInboxReportLink";
1514

1615
interface ReportDetailProps {
1716
reportId: string;
@@ -36,16 +35,6 @@ export function ReportDetail({
3635
}
3736

3837
function ReportDetailContent({ report }: { report: SignalReport }) {
39-
const handleCopyLink = () => {
40-
const url = buildInboxDeeplink(report.id, report.title, {
41-
isDevBuild: import.meta.env.DEV,
42-
});
43-
navigator.clipboard
44-
.writeText(url)
45-
.then(() => toast.success("Link copied"))
46-
.catch(() => toast.error("Couldn't copy link"));
47-
};
48-
4938
return (
5039
<InboxDetailFrame
5140
report={report}
@@ -59,7 +48,7 @@ function ReportDetailContent({ report }: { report: SignalReport }) {
5948
type="button"
6049
variant="outline"
6150
size="sm"
62-
onClick={handleCopyLink}
51+
onClick={() => copyInboxReportLink(report)}
6352
title="Copy a deep link to this report"
6453
>
6554
<CopyIcon size={12} />
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { buildInboxDeeplink } from "@posthog/shared/deeplink";
2+
import type { SignalReport } from "@posthog/shared/types";
3+
import { toast } from "sonner";
4+
5+
/**
6+
* Copy a deep link (`<scheme>://inbox/{reportId}`) for an inbox report to the
7+
* clipboard, toasting success or failure. Shared by every inbox detail surface
8+
* (reports, runs, pull requests) so the link format and copy feedback stay in
9+
* one place. The inbound side of these links lives in `useInboxDeepLink`.
10+
*/
11+
export function copyInboxReportLink(
12+
report: Pick<SignalReport, "id" | "title">,
13+
): void {
14+
const url = buildInboxDeeplink(report.id, report.title, {
15+
isDevBuild: import.meta.env.DEV,
16+
});
17+
navigator.clipboard
18+
.writeText(url)
19+
.then(() => toast.success("Link copied"))
20+
.catch(() => toast.error("Couldn't copy link"));
21+
}

0 commit comments

Comments
 (0)