| author | |
| committer | |
| log | d7c71f91d61e68ae35fcc0032847cb42324a8b51 |
| tree | 8ff17e1d3c2a8fa312369f847923366c7709a503 |
| parent | 21d53ca2eecbf9f1e481454e8084459b422de714 |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: maria-rcks <254055478+maria-rcks@users.noreply.github.com>4 files changed, 200 insertions(+), 145 deletions(-)
apps/web/src/components/pullRequest/PullRequestCodeTab.tsx+14-4| ... | @@ -961,7 +961,14 @@ function PullRequestCodeTab({ | ... | @@ -961,7 +961,14 @@ function PullRequestCodeTab({ |
| 961 | review.verdicts.length === 0 ? null : ( | 961 | review.verdicts.length === 0 ? null : ( |
| 962 | <div className="pointer-events-none absolute inset-x-0 bottom-0 z-10"> | 962 | <div className="pointer-events-none absolute inset-x-0 bottom-0 z-10"> |
| 963 | {reviewOpen ? ( | 963 | {reviewOpen ? ( |
| 964 | <div className="surface-glass pointer-events-auto absolute inset-x-3 bottom-3 rounded-xl border border-border/60 shadow-lg"> | 964 | <div |
| 965 | className={cn( | ||
| 966 | "surface-glass pointer-events-auto absolute inset-x-3 rounded-xl border border-border/60 shadow-lg", | ||
| 967 | detail.capabilities.comment && detail.viewerPermissions.comment | ||
| 968 | ? "bottom-16" | ||
| 969 | : "bottom-3", | ||
| 970 | )} | ||
| 971 | > | ||
| 965 | <Button | 972 | <Button |
| 966 | type="button" | 973 | type="button" |
| 967 | size="icon-sm" | 974 | size="icon-sm" |
| ... | @@ -984,10 +991,13 @@ function PullRequestCodeTab({ | ... | @@ -984,10 +991,13 @@ function PullRequestCodeTab({ |
| 984 | /> | 991 | /> |
| 985 | </div> | 992 | </div> |
| 986 | ) : ( | 993 | ) : ( |
| 987 | // Bottom-right, clear of the vertical scrollbar the diff view keeps to its own right | ||
| 988 | // edge. | ||
| 989 | <Button | 994 | <Button |
| 990 | className="pointer-events-auto absolute right-4 bottom-3 rounded-full shadow-lg" | 995 | className={cn( |
| 996 | "pointer-events-auto absolute bottom-3 rounded-full shadow-lg", | ||
| 997 | detail.capabilities.comment && detail.viewerPermissions.comment | ||
| 998 | ? "right-16" | ||
| 999 | : "right-4", | ||
| 1000 | )} | ||
| 991 | onClick={() => setReviewOpen(true)} | 1001 | onClick={() => setReviewOpen(true)} |
| 992 | size="compact" | 1002 | size="compact" |
| 993 | variant="glass" | 1003 | variant="glass" |
apps/web/src/components/pullRequest/PullRequestCommentComposer.tsx created+163| ... | @@ -0,0 +1,163 @@ | ||
| 1 | import type { EnvironmentId, PullRequestDetailView, PullRequestRef } from "@t3tools/contracts"; | ||
| 2 | import { | ||
| 3 | GitPullRequestClosedIcon, | ||
| 4 | MessageSquareIcon, | ||
| 5 | RotateCcwIcon, | ||
| 6 | SendIcon, | ||
| 7 | XIcon, | ||
| 8 | } from "lucide-react"; | ||
| 9 | import { useRef, useState } from "react"; | ||
| 10 | |||
| 11 | import { useAtomCommand } from "~/state/use-atom-command"; | ||
| 12 | import { pullRequestEnvironment } from "~/state/pullRequests"; | ||
| 13 | |||
| 14 | import { Button } from "../ui/button"; | ||
| 15 | import { Popover, PopoverClose, PopoverPopup, PopoverTitle, PopoverTrigger } from "../ui/popover"; | ||
| 16 | import { Textarea } from "../ui/textarea"; | ||
| 17 | import { toastManager } from "../ui/toast"; | ||
| 18 | |||
| 19 | export function PullRequestCommentComposer({ | ||
| 20 | environmentId, | ||
| 21 | reference, | ||
| 22 | detail, | ||
| 23 | actionPending, | ||
| 24 | onCommentAction, | ||
| 25 | onCommented, | ||
| 26 | }: { | ||
| 27 | environmentId: EnvironmentId; | ||
| 28 | reference: PullRequestRef; | ||
| 29 | detail: PullRequestDetailView; | ||
| 30 | actionPending: boolean; | ||
| 31 | onCommentAction: ( | ||
| 32 | body: string, | ||
| 33 | action: "close" | "reopen", | ||
| 34 | ) => Promise<{ readonly commentPosted: boolean }>; | ||
| 35 | onCommented: () => void; | ||
| 36 | }) { | ||
| 37 | const [open, setOpen] = useState(false); | ||
| 38 | const [body, setBody] = useState(""); | ||
| 39 | const [submitting, setSubmitting] = useState<"comment" | "close" | "reopen" | null>(null); | ||
| 40 | const textareaRef = useRef<HTMLTextAreaElement>(null); | ||
| 41 | const postComment = useAtomCommand(pullRequestEnvironment.comment, { reportFailure: false }); | ||
| 42 | const followUpAction = | ||
| 43 | detail.state === "open" && | ||
| 44 | detail.capabilities.actions.includes("close") && | ||
| 45 | detail.viewerPermissions.actions.includes("close") | ||
| 46 | ? ("close" as const) | ||
| 47 | : detail.state === "closed" && | ||
| 48 | detail.capabilities.actions.includes("reopen") && | ||
| 49 | detail.viewerPermissions.actions.includes("reopen") | ||
| 50 | ? ("reopen" as const) | ||
| 51 | : null; | ||
| 52 | |||
| 53 | const submit = async (action: "comment" | "close" | "reopen") => { | ||
| 54 | const trimmed = body.trim(); | ||
| 55 | if (trimmed.length === 0 || submitting !== null || actionPending) return; | ||
| 56 | setSubmitting(action); | ||
| 57 | if (action !== "comment") { | ||
| 58 | const result = await onCommentAction(trimmed, action); | ||
| 59 | if (result.commentPosted) { | ||
| 60 | setBody(""); | ||
| 61 | setOpen(false); | ||
| 62 | } | ||
| 63 | setSubmitting(null); | ||
| 64 | return; | ||
| 65 | } | ||
| 66 | const result = await postComment({ | ||
| 67 | environmentId, | ||
| 68 | input: { | ||
| 69 | ...reference, | ||
| 70 | body: trimmed, | ||
| 71 | }, | ||
| 72 | }); | ||
| 73 | if (result._tag === "Failure") { | ||
| 74 | setSubmitting(null); | ||
| 75 | toastManager.add({ type: "error", title: "Could not post the comment" }); | ||
| 76 | return; | ||
| 77 | } | ||
| 78 | setBody(""); | ||
| 79 | setSubmitting(null); | ||
| 80 | setOpen(false); | ||
| 81 | onCommented(); | ||
| 82 | }; | ||
| 83 | |||
| 84 | return ( | ||
| 85 | <Popover open={open} onOpenChange={setOpen}> | ||
| 86 | <PopoverTrigger | ||
| 87 | render={ | ||
| 88 | <Button | ||
| 89 | size="icon" | ||
| 90 | variant="glass" | ||
| 91 | className="rounded-full shadow-lg [--glass-opacity:50%]" | ||
| 92 | /> | ||
| 93 | } | ||
| 94 | aria-label="Comment on pull request" | ||
| 95 | > | ||
| 96 | <MessageSquareIcon className="size-4" /> | ||
| 97 | </PopoverTrigger> | ||
| 98 | <PopoverPopup | ||
| 99 | side="top" | ||
| 100 | align="end" | ||
| 101 | sideOffset={8} | ||
| 102 | className="w-96 max-w-[calc(100vw-2rem)]" | ||
| 103 | initialFocus={textareaRef} | ||
| 104 | > | ||
| 105 | <div className="mb-3 flex items-center justify-between gap-2"> | ||
| 106 | <PopoverTitle className="text-sm">Comment on pull request</PopoverTitle> | ||
| 107 | <PopoverClose | ||
| 108 | render={<Button size="icon-xs" variant="ghost" />} | ||
| 109 | aria-label="Close comment composer" | ||
| 110 | > | ||
| 111 | <XIcon className="size-3.5" /> | ||
| 112 | </PopoverClose> | ||
| 113 | </div> | ||
| 114 | <div className="space-y-2"> | ||
| 115 | <Textarea | ||
| 116 | ref={textareaRef} | ||
| 117 | className="[&_textarea]:max-h-64" | ||
| 118 | // Locked while posting: the body is cleared on success, which would otherwise throw | ||
| 119 | // away a new draft typed while the request was still in flight. | ||
| 120 | disabled={submitting !== null || actionPending} | ||
| 121 | value={body} | ||
| 122 | rows={3} | ||
| 123 | placeholder="Leave a comment" | ||
| 124 | aria-label="Comment on this pull request" | ||
| 125 | onChange={(event) => setBody(event.target.value)} | ||
| 126 | /> | ||
| 127 | <div className="flex flex-wrap justify-end gap-2"> | ||
| 128 | {followUpAction === null ? null : ( | ||
| 129 | <Button | ||
| 130 | size="xs" | ||
| 131 | variant={followUpAction === "close" ? "destructive-outline" : "outline"} | ||
| 132 | disabled={body.trim().length === 0 || submitting !== null || actionPending} | ||
| 133 | onClick={() => void submit(followUpAction)} | ||
| 134 | > | ||
| 135 | {followUpAction === "close" ? ( | ||
| 136 | <GitPullRequestClosedIcon className="size-3.5" /> | ||
| 137 | ) : ( | ||
| 138 | <RotateCcwIcon className="size-3.5" /> | ||
| 139 | )} | ||
| 140 | {submitting === followUpAction | ||
| 141 | ? followUpAction === "close" | ||
| 142 | ? "Closing..." | ||
| 143 | : "Reopening..." | ||
| 144 | : followUpAction === "close" | ||
| 145 | ? "Close with comment" | ||
| 146 | : "Reopen with comment"} | ||
| 147 | </Button> | ||
| 148 | )} | ||
| 149 | <Button | ||
| 150 | size="xs" | ||
| 151 | variant="outline" | ||
| 152 | disabled={body.trim().length === 0 || submitting !== null || actionPending} | ||
| 153 | onClick={() => void submit("comment")} | ||
| 154 | > | ||
| 155 | <SendIcon className="size-3.5" /> | ||
| 156 | {submitting === "comment" ? "Posting..." : "Comment"} | ||
| 157 | </Button> | ||
| 158 | </div> | ||
| 159 | </div> | ||
| 160 | </PopoverPopup> | ||
| 161 | </Popover> | ||
| 162 | ); | ||
| 163 | } | ||
apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx+23-3| ... | @@ -116,6 +116,7 @@ import { PullRequestsUnavailableState } from "./PullRequestsUnavailableState"; | ... | @@ -116,6 +116,7 @@ import { PullRequestsUnavailableState } from "./PullRequestsUnavailableState"; |
| 116 | import type { PullRequestAgentSelectionInput } from "./PullRequestCodeTab"; | 116 | import type { PullRequestAgentSelectionInput } from "./PullRequestCodeTab"; |
| 117 | import { openOnHostLabel, showPullRequestLinkContextMenu } from "./pullRequestLinkContextMenu"; | 117 | import { openOnHostLabel, showPullRequestLinkContextMenu } from "./pullRequestLinkContextMenu"; |
| 118 | import { PullRequestMarkdownContext } from "./PullRequestMarkdown"; | 118 | import { PullRequestMarkdownContext } from "./PullRequestMarkdown"; |
| 119 | import { PullRequestCommentComposer } from "./PullRequestCommentComposer"; | ||
| 119 | import { PullRequestSummaryTab } from "./PullRequestSummaryTab"; | 120 | import { PullRequestSummaryTab } from "./PullRequestSummaryTab"; |
| 120 | import { PullRequestTimelineTab } from "./PullRequestTimelineTab"; | 121 | import { PullRequestTimelineTab } from "./PullRequestTimelineTab"; |
| 121 | import { | 122 | import { |
| ... | @@ -1480,7 +1481,7 @@ export function PullRequestDetailPanel({ | ... | @@ -1480,7 +1481,7 @@ export function PullRequestDetailPanel({ |
| 1480 | } | 1481 | } |
| 1481 | 1482 | ||
| 1482 | return ( | 1483 | return ( |
| 1483 | <div className="flex h-full min-h-0 w-full flex-col bg-background"> | 1484 | <div className="relative flex h-full min-h-0 w-full flex-col bg-background"> |
| 1484 | {threadPickerOpen && detail ? ( | 1485 | {threadPickerOpen && detail ? ( |
| 1485 | <PullRequestThreadLinks | 1486 | <PullRequestThreadLinks |
| 1486 | key={`${environmentId}:${detail.url}`} | 1487 | key={`${environmentId}:${detail.url}`} |
| ... | @@ -2612,8 +2613,6 @@ export function PullRequestDetailPanel({ | ... | @@ -2612,8 +2613,6 @@ export function PullRequestDetailPanel({ |
| 2612 | fixFindingLabel={handoffLabels.fixFinding} | 2613 | fixFindingLabel={handoffLabels.fixFinding} |
| 2613 | fixCheckLabel={handoffLabels.fixCheck} | 2614 | fixCheckLabel={handoffLabels.fixCheck} |
| 2614 | onFixFinding={startFixFinding} | 2615 | onFixFinding={startFixFinding} |
| 2615 | actionPending={actionPending} | ||
| 2616 | onCommentAction={performCommentAction} | ||
| 2617 | onRefresh={refreshDetail} | 2616 | onRefresh={refreshDetail} |
| 2618 | /> | 2617 | /> |
| 2619 | </div> | 2618 | </div> |
| ... | @@ -2663,6 +2662,27 @@ export function PullRequestDetailPanel({ | ... | @@ -2663,6 +2662,27 @@ export function PullRequestDetailPanel({ |
| 2663 | ) : null} | 2662 | ) : null} |
| 2664 | </div> | 2663 | </div> |
| 2665 | 2664 | ||
| 2665 | {/* Float over the content; do not reserve a footer or padding in the PR tabs. */} | ||
| 2666 | {detail?.capabilities.comment && detail.viewerPermissions.comment ? ( | ||
| 2667 | <div className="absolute right-4 bottom-3 z-20"> | ||
| 2668 | <PullRequestCommentComposer | ||
| 2669 | key={JSON.stringify([ | ||
| 2670 | environmentId, | ||
| 2671 | reference.projectId, | ||
| 2672 | reference.host, | ||
| 2673 | reference.repository, | ||
| 2674 | reference.number, | ||
| 2675 | ])} | ||
| 2676 | environmentId={environmentId} | ||
| 2677 | reference={reference} | ||
| 2678 | detail={detail} | ||
| 2679 | actionPending={actionPending} | ||
| 2680 | onCommentAction={performCommentAction} | ||
| 2681 | onCommented={refreshDetail} | ||
| 2682 | /> | ||
| 2683 | </div> | ||
| 2684 | ) : null} | ||
| 2685 | |||
| 2666 | <AlertDialog | 2686 | <AlertDialog |
| 2667 | open={confirmation.open} | 2687 | open={confirmation.open} |
| 2668 | onOpenChange={(open) => setConfirmation((current) => ({ ...current, open }))} | 2688 | onOpenChange={(open) => setConfirmation((current) => ({ ...current, open }))} |
apps/web/src/components/pullRequest/PullRequestSummaryTab.tsx-138| ... | @@ -10,11 +10,8 @@ import { | ... | @@ -10,11 +10,8 @@ import { |
| 10 | ArrowDownUpIcon, | 10 | ArrowDownUpIcon, |
| 11 | ChevronDownIcon, | 11 | ChevronDownIcon, |
| 12 | ChevronRightIcon, | 12 | ChevronRightIcon, |
| 13 | GitPullRequestClosedIcon, | ||
| 14 | HammerIcon, | 13 | HammerIcon, |
| 15 | PencilIcon, | 14 | PencilIcon, |
| 16 | RotateCcwIcon, | ||
| 17 | SendIcon, | ||
| 18 | TagIcon, | 15 | TagIcon, |
| 19 | UsersIcon, | 16 | UsersIcon, |
| 20 | } from "lucide-react"; | 17 | } from "lucide-react"; |
| ... | @@ -28,7 +25,6 @@ import { formatRelativeTimeLabel } from "~/timestampFormat"; | ... | @@ -28,7 +25,6 @@ import { formatRelativeTimeLabel } from "~/timestampFormat"; |
| 28 | 25 | ||
| 29 | import { Button } from "../ui/button"; | 26 | import { Button } from "../ui/button"; |
| 30 | import { Collapsible, CollapsiblePanel, CollapsibleTrigger } from "../ui/collapsible"; | 27 | import { Collapsible, CollapsiblePanel, CollapsibleTrigger } from "../ui/collapsible"; |
| 31 | import { Textarea } from "../ui/textarea"; | ||
| 32 | import { toastManager } from "../ui/toast"; | 28 | import { toastManager } from "../ui/toast"; |
| 33 | import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; | 29 | import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; |
| 34 | import { | 30 | import { |
| ... | @@ -303,113 +299,6 @@ function Section({ | ... | @@ -303,113 +299,6 @@ function Section({ |
| 303 | ); | 299 | ); |
| 304 | } | 300 | } |
| 305 | 301 | ||
| 306 | function CommentComposer({ | ||
| 307 | environmentId, | ||
| 308 | reference, | ||
| 309 | detail, | ||
| 310 | actionPending, | ||
| 311 | onCommentAction, | ||
| 312 | onCommented, | ||
| 313 | }: { | ||
| 314 | environmentId: EnvironmentId; | ||
| 315 | reference: PullRequestRef; | ||
| 316 | detail: PullRequestDetailView; | ||
| 317 | actionPending: boolean; | ||
| 318 | onCommentAction: ( | ||
| 319 | body: string, | ||
| 320 | action: "close" | "reopen", | ||
| 321 | ) => Promise<{ readonly commentPosted: boolean }>; | ||
| 322 | onCommented: () => void; | ||
| 323 | }) { | ||
| 324 | const [body, setBody] = useState(""); | ||
| 325 | const [submitting, setSubmitting] = useState<"comment" | "close" | "reopen" | null>(null); | ||
| 326 | const postComment = useAtomCommand(pullRequestEnvironment.comment, { reportFailure: false }); | ||
| 327 | const followUpAction = | ||
| 328 | detail.state === "open" && | ||
| 329 | detail.capabilities.actions.includes("close") && | ||
| 330 | detail.viewerPermissions.actions.includes("close") | ||
| 331 | ? ("close" as const) | ||
| 332 | : detail.state === "closed" && | ||
| 333 | detail.capabilities.actions.includes("reopen") && | ||
| 334 | detail.viewerPermissions.actions.includes("reopen") | ||
| 335 | ? ("reopen" as const) | ||
| 336 | : null; | ||
| 337 | |||
| 338 | const submit = async (action: "comment" | "close" | "reopen") => { | ||
| 339 | const trimmed = body.trim(); | ||
| 340 | if (trimmed.length === 0 || submitting !== null || actionPending) return; | ||
| 341 | setSubmitting(action); | ||
| 342 | if (action !== "comment") { | ||
| 343 | const result = await onCommentAction(trimmed, action); | ||
| 344 | if (result.commentPosted) setBody(""); | ||
| 345 | setSubmitting(null); | ||
| 346 | return; | ||
| 347 | } | ||
| 348 | const result = await postComment({ | ||
| 349 | environmentId, | ||
| 350 | input: { | ||
| 351 | ...reference, | ||
| 352 | body: trimmed, | ||
| 353 | }, | ||
| 354 | }); | ||
| 355 | if (result._tag === "Failure") { | ||
| 356 | setSubmitting(null); | ||
| 357 | toastManager.add({ type: "error", title: "Could not post the comment" }); | ||
| 358 | return; | ||
| 359 | } | ||
| 360 | setBody(""); | ||
| 361 | setSubmitting(null); | ||
| 362 | onCommented(); | ||
| 363 | }; | ||
| 364 | |||
| 365 | return ( | ||
| 366 | <div className="space-y-2"> | ||
| 367 | <Textarea | ||
| 368 | // Locked while posting: the body is cleared on success, which would otherwise throw | ||
| 369 | // away a new draft typed while the request was still in flight. | ||
| 370 | disabled={submitting !== null || actionPending} | ||
| 371 | value={body} | ||
| 372 | rows={3} | ||
| 373 | placeholder="Leave a comment" | ||
| 374 | aria-label="Comment on this pull request" | ||
| 375 | onChange={(event) => setBody(event.target.value)} | ||
| 376 | /> | ||
| 377 | <div className="flex justify-end gap-2"> | ||
| 378 | {followUpAction === null ? null : ( | ||
| 379 | <Button | ||
| 380 | size="xs" | ||
| 381 | variant={followUpAction === "close" ? "destructive-outline" : "outline"} | ||
| 382 | disabled={body.trim().length === 0 || submitting !== null || actionPending} | ||
| 383 | onClick={() => void submit(followUpAction)} | ||
| 384 | > | ||
| 385 | {followUpAction === "close" ? ( | ||
| 386 | <GitPullRequestClosedIcon className="size-3.5" /> | ||
| 387 | ) : ( | ||
| 388 | <RotateCcwIcon className="size-3.5" /> | ||
| 389 | )} | ||
| 390 | {submitting === followUpAction | ||
| 391 | ? followUpAction === "close" | ||
| 392 | ? "Closing..." | ||
| 393 | : "Reopening..." | ||
| 394 | : followUpAction === "close" | ||
| 395 | ? "Close with comment" | ||
| 396 | : "Reopen with comment"} | ||
| 397 | </Button> | ||
| 398 | )} | ||
| 399 | <Button | ||
| 400 | size="xs" | ||
| 401 | variant="outline" | ||
| 402 | disabled={body.trim().length === 0 || submitting !== null || actionPending} | ||
| 403 | onClick={() => void submit("comment")} | ||
| 404 | > | ||
| 405 | <SendIcon className="size-3.5" /> | ||
| 406 | {submitting === "comment" ? "Posting..." : "Comment"} | ||
| 407 | </Button> | ||
| 408 | </div> | ||
| 409 | </div> | ||
| 410 | ); | ||
| 411 | } | ||
| 412 | |||
| 413 | /** | 302 | /** |
| 414 | * What a first render of the conversation carries. A pull request with two hundred comments is | 303 | * What a first render of the conversation carries. A pull request with two hundred comments is |
| 415 | * two hundred markdown documents, and the ones worth arriving for are the recent ones. | 304 | * two hundred markdown documents, and the ones worth arriving for are the recent ones. |
| ... | @@ -427,8 +316,6 @@ export function PullRequestSummaryTab({ | ... | @@ -427,8 +316,6 @@ export function PullRequestSummaryTab({ |
| 427 | fixFindingLabel = "Fix in a thread", | 316 | fixFindingLabel = "Fix in a thread", |
| 428 | fixCheckLabel = "Fix", | 317 | fixCheckLabel = "Fix", |
| 429 | onFixFinding, | 318 | onFixFinding, |
| 430 | actionPending, | ||
| 431 | onCommentAction, | ||
| 432 | onRefresh, | 319 | onRefresh, |
| 433 | }: { | 320 | }: { |
| 434 | environmentId: EnvironmentId; | 321 | environmentId: EnvironmentId; |
| ... | @@ -442,11 +329,6 @@ export function PullRequestSummaryTab({ | ... | @@ -442,11 +329,6 @@ export function PullRequestSummaryTab({ |
| 442 | fixFindingLabel?: string; | 329 | fixFindingLabel?: string; |
| 443 | fixCheckLabel?: string; | 330 | fixCheckLabel?: string; |
| 444 | onFixFinding?: (finding: PullRequestFinding) => void; | 331 | onFixFinding?: (finding: PullRequestFinding) => void; |
| 445 | actionPending: boolean; | ||
| 446 | onCommentAction: ( | ||
| 447 | body: string, | ||
| 448 | action: "close" | "reopen", | ||
| 449 | ) => Promise<{ readonly commentPosted: boolean }>; | ||
| 450 | onRefresh: () => void; | 332 | onRefresh: () => void; |
| 451 | }) { | 333 | }) { |
| 452 | // Keyed by the pull request, so opening another one starts at the end of its conversation | 334 | // Keyed by the pull request, so opening another one starts at the end of its conversation |
| ... | @@ -984,26 +866,6 @@ export function PullRequestSummaryTab({ | ... | @@ -984,26 +866,6 @@ export function PullRequestSummaryTab({ |
| 984 | </> | 866 | </> |
| 985 | )} | 867 | )} |
| 986 | </Section> | 868 | </Section> |
| 987 | <div className="px-4 pb-4"> | ||
| 988 | {/* Posting stays available when the conversation is folded or its activity read failed. */} | ||
| 989 | {detail.capabilities.comment && detail.viewerPermissions.comment ? ( | ||
| 990 | <CommentComposer | ||
| 991 | reference={reference} | ||
| 992 | key={JSON.stringify([ | ||
| 993 | environmentId, | ||
| 994 | reference.projectId, | ||
| 995 | reference.host, | ||
| 996 | reference.repository, | ||
| 997 | reference.number, | ||
| 998 | ])} | ||
| 999 | environmentId={environmentId} | ||
| 1000 | detail={detail} | ||
| 1001 | actionPending={actionPending} | ||
| 1002 | onCommentAction={onCommentAction} | ||
| 1003 | onCommented={onRefresh} | ||
| 1004 | /> | ||
| 1005 | ) : null} | ||
| 1006 | </div> | ||
| 1007 | </div> | 869 | </div> |
| 1008 | ); | 870 | ); |
| 1009 | } | 871 | } |