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"}
{/* Keyed by position as well as by name: the host is the one that decides how many runs
share a name, and a repeated key is a rendering fault rather than a wrong list. */}
{checks.map((check, index) => (
);
}
/**
* 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()}
>