import type { EnvironmentId, PullRequestCheck, PullRequestChecksState, PullRequestRef, ScopedThreadRef, } from "@t3tools/contracts"; import { useOpenLink } from "~/browser/useOpenLink"; import { cn } from "~/lib/utils"; import { pullRequestEnvironment } from "~/state/pullRequests"; import { useEnvironmentQuery } from "~/state/query"; import { Popover, PopoverPopup, PopoverTrigger } from "../ui/popover"; import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; import { toastManager } from "../ui/toast"; import { PullRequestCheckStatusIcon, pullRequestCheckStatusLabel, pullRequestChecksStatePresentation, summarizePullRequestChecks, } from "./pullRequestPresentation"; /** * The checks behind the rollup, for a row that only carries the rollup. Mounted by the popup, so * the read starts when somebody opens it rather than once per row of a listing — the detail read * is a request per pull request, and a page of them at rest would be a hundred. */ function LazyChecksBody({ environmentId, reference, threadRef, }: { environmentId: EnvironmentId; reference: PullRequestRef; threadRef: ScopedThreadRef | null; }) { const detailQuery = useEnvironmentQuery( pullRequestEnvironment.detail({ environmentId, input: reference }), ); if (detailQuery.error !== null) { return

{detailQuery.error}

; } if (detailQuery.data === null) { return (

{detailQuery.isPending ? "Loading checks…" : "No checks reported"}

); } return ; } function ChecksBody({ checks, threadRef, }: { checks: ReadonlyArray; threadRef: ScopedThreadRef | null; }) { const openLink = useOpenLink(threadRef); if (checks.length === 0) { return

No checks reported

; } return ( ); } /** * The checks indicator and what it opens, in both places a change request is shown: a listing * row, which knows only the rollup, and the detail header, which is already holding every check. * * `checks` decides between the two. Given them, nothing is read; without them, the popup reads * the detail itself, which is why the row must also say which environment it came from. */ export function PullRequestChecksPopover({ checksState, checks, environmentId, reference, threadRef = null, className, }: { checksState: PullRequestChecksState; /** The checks already in hand, for the detail header. Absent on a listing row. */ checks?: ReadonlyArray; environmentId?: EnvironmentId; reference?: PullRequestRef; /** Thread the popover sits beside; a listing row has none. */ threadRef?: ScopedThreadRef | null; className?: string; }) { const presentation = pullRequestChecksStatePresentation(checksState); // Counts beat the rollup's own wording where they are known, the way GitHub's own header reads. const summary = checks === undefined ? null : summarizePullRequestChecks(checks); return ( {/* A listing row is itself a button, so the trigger renders as a span: a nested button is not valid inside one. The click is stopped here so opening the checks does not also select the row it sits on. */} } onClick={(event) => event.stopPropagation()} >

{presentation.label}

{summary === null ? null :

{summary}

} {checks !== undefined ? ( ) : environmentId !== undefined && reference !== undefined ? ( ) : null}
); }