Skip to content

Commit 62d5595

Browse files
committed
feat(desktop): wire up the Share button on the PR detail page
Surfaces the AI review already published for a PR via a new ReviewSharePopover — reads review.getForPullRequest, shows a disabled tooltip when nothing's shared yet, and lets an org member toggle visibility on an existing review through page.setVisibility.
1 parent b05a747 commit 62d5595

4 files changed

Lines changed: 139 additions & 2 deletions

File tree

apps/desktop/src/renderer/lib/cloud-trpc.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export const CLOUD_TRPC_ROUTER_ROOTS = [
4141
"organization",
4242
"page",
4343
"pageComment",
44+
"review",
4445
"support",
4546
"task",
4647
"team",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import { Button } from "@superset/ui/button";
2+
import { Label } from "@superset/ui/label";
3+
import { Popover, PopoverContent, PopoverTrigger } from "@superset/ui/popover";
4+
import {
5+
Select,
6+
SelectContent,
7+
SelectItem,
8+
SelectTrigger,
9+
SelectValue,
10+
} from "@superset/ui/select";
11+
import { Separator } from "@superset/ui/separator";
12+
import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip";
13+
import { useState } from "react";
14+
import {
15+
LuBuilding2,
16+
LuCheck,
17+
LuLink2,
18+
LuLock,
19+
LuShare2,
20+
} from "react-icons/lu";
21+
import { useCopyToClipboard } from "renderer/hooks/useCopyToClipboard";
22+
import { cloudTrpc } from "renderer/lib/cloud-trpc";
23+
24+
interface ReviewSharePopoverProps {
25+
prUrl: string;
26+
}
27+
28+
/**
29+
* Surfaces the AI code review already published for this PR (via
30+
* `reviews_publish` — an external, agent-driven action, not something this
31+
* view can trigger itself: it has no findings to publish). Reviews reuse the
32+
* generic Pages table, so visibility is changed through `page.setVisibility`
33+
* the same way the Pages share popover does.
34+
*/
35+
export function ReviewSharePopover({ prUrl }: ReviewSharePopoverProps) {
36+
const [open, setOpen] = useState(false);
37+
const { copyToClipboard, copied } = useCopyToClipboard();
38+
39+
const review = cloudTrpc.review.getForPullRequest.useQuery(
40+
{ prUrl },
41+
{ enabled: Boolean(prUrl) },
42+
);
43+
const setVisibility = cloudTrpc.page.setVisibility.useMutation({
44+
onSuccess: () => void review.refetch(),
45+
});
46+
47+
const page = review.data;
48+
const iconButton = (
49+
<Button
50+
variant="ghost"
51+
size="icon-sm"
52+
disabled={!page}
53+
aria-label={page ? "Share AI review" : "No AI review shared yet"}
54+
>
55+
<LuShare2 className="size-4" />
56+
</Button>
57+
);
58+
59+
if (!page) {
60+
return (
61+
<Tooltip delayDuration={300}>
62+
<TooltipTrigger asChild>
63+
{/* A disabled button still lets a wrapping span pick up the
64+
hover that opens the tooltip. */}
65+
<span>{iconButton}</span>
66+
</TooltipTrigger>
67+
<TooltipContent side="bottom">
68+
{review.isLoading
69+
? "Checking for a shared review…"
70+
: "No AI review has been shared for this PR yet"}
71+
</TooltipContent>
72+
</Tooltip>
73+
);
74+
}
75+
76+
return (
77+
<Popover open={open} onOpenChange={setOpen}>
78+
<PopoverTrigger asChild>{iconButton}</PopoverTrigger>
79+
<PopoverContent align="end" className="w-80 p-0">
80+
<div className="flex items-center justify-between gap-2 px-3 py-2.5">
81+
<span className="min-w-0 truncate font-medium text-sm">
82+
{page.title}
83+
</span>
84+
<Button
85+
size="xs"
86+
variant="ghost"
87+
onClick={() => void copyToClipboard(page.url)}
88+
>
89+
{copied ? (
90+
<LuCheck className="size-3.5 text-primary" />
91+
) : (
92+
<LuLink2 className="size-3.5" />
93+
)}
94+
{copied ? "Copied" : "Copy link"}
95+
</Button>
96+
</div>
97+
<Separator />
98+
<div className="space-y-2 px-3 py-2.5">
99+
<div className="space-y-0.5">
100+
<Label className="font-medium text-sm">General access</Label>
101+
<p className="text-muted-foreground text-xs">
102+
Who can open this review from its link
103+
</p>
104+
</div>
105+
<Select
106+
value={page.visibility}
107+
disabled={setVisibility.isPending}
108+
onValueChange={(value) =>
109+
setVisibility.mutate({
110+
id: page.id,
111+
visibility: value as "just_me" | "org",
112+
})
113+
}
114+
>
115+
<SelectTrigger size="sm" className="w-full">
116+
<SelectValue />
117+
</SelectTrigger>
118+
<SelectContent>
119+
<SelectItem value="just_me">
120+
<LuLock className="size-3.5 text-muted-foreground" />
121+
Only you
122+
</SelectItem>
123+
<SelectItem value="org">
124+
<LuBuilding2 className="size-3.5 text-muted-foreground" />
125+
Anyone in your organization
126+
</SelectItem>
127+
</SelectContent>
128+
</Select>
129+
</div>
130+
</PopoverContent>
131+
</Popover>
132+
);
133+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { ReviewSharePopover } from "./ReviewSharePopover";

apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/$prNumber/page.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import {
5151
import { useOpenNewWorkspaceModal } from "renderer/stores/new-workspace-modal";
5252
import { Route as PullRequestsLayoutRoute } from "../layout";
5353
import { PullRequestCodeTab } from "./components/PullRequestCodeTab";
54+
import { ReviewSharePopover } from "./components/ReviewSharePopover";
5455

5556
export const Route = createFileRoute(
5657
"/_authenticated/_dashboard/pull-requests/$prNumber/",
@@ -272,8 +273,9 @@ function PullRequestDetailPage() {
272273
</div>
273274
{/* Window-drag leaf standing in for the hidden TopBar. */}
274275
<div className="drag h-full min-w-0 flex-1" />
275-
{/* Share and the "..." overflow (close/reopen) are coming soon —
276-
both hidden until they have real functionality wired up. */}
276+
{data && <ReviewSharePopover prUrl={data.url} />}
277+
{/* The "..." overflow (close/reopen) is coming soon — hidden until
278+
it has real functionality wired up. */}
277279
</div>
278280

279281
<div className="flex flex-wrap items-start justify-between gap-3 px-4 pb-3">

0 commit comments

Comments
 (0)