138 lines · 5.1 KB · TypeScript
RawDownload
import type {  EnvironmentId,  PullRequestCheck,  PullRequestChecksState,  PullRequestRef,} from "@t3tools/contracts"; import { readLocalApi } from "~/localApi";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 {  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,}: {  environmentId: EnvironmentId;  reference: PullRequestRef;}) {  const detailQuery = useEnvironmentQuery(    pullRequestEnvironment.detail({ environmentId, input: reference }),  );  if (detailQuery.error !== null) {    return <p className="text-muted-foreground text-xs">{detailQuery.error}</p>;  }  if (detailQuery.data === null) {    return (      <p className="text-muted-foreground text-xs">        {detailQuery.isPending ? "Loading checks…" : "No checks reported"}      </p>    );  }  return <ChecksBody checks={detailQuery.data.checks} />;} function ChecksBody({ checks }: { checks: ReadonlyArray<PullRequestCheck> }) {  if (checks.length === 0) {    return <p className="text-muted-foreground text-xs">No checks reported</p>;  }  return (    <ul className="flex flex-col gap-1">      {/* 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) => (        <li key={`${index}:${check.name}`} className="flex items-center gap-2 text-xs">          <PullRequestCheckStatusIcon status={check.status} />          <Tooltip>            <TooltipTrigger              render={<span className="min-w-0 flex-1 truncate">{check.name}</span>}            />            <TooltipPopup side="top">{check.description ?? check.name}</TooltipPopup>          </Tooltip>          <span className="shrink-0 text-muted-foreground">            {pullRequestCheckStatusLabel(check.status)}          </span>          {check.url === null ? null : (            <button              type="button"              className="shrink-0 text-primary hover:underline"              onClick={() => void readLocalApi()?.shell.openExternal(check.url ?? "")}            >              Details            </button>          )}        </li>      ))}    </ul>  );} /** * 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,  className,}: {  checksState: PullRequestChecksState;  /** The checks already in hand, for the detail header. Absent on a listing row. */  checks?: ReadonlyArray<PullRequestCheck>;  environmentId?: EnvironmentId;  reference?: PullRequestRef;  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 (    <Popover>      {/* 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. */}      <PopoverTrigger        render={          <span            role="button"            tabIndex={0}            aria-label={`Checks: ${presentation.label}`}            className={cn("inline-flex shrink-0 cursor-pointer items-center", className)}          />        }        onClick={(event) => event.stopPropagation()}      >        <presentation.Icon aria-hidden className={cn("size-3.5", presentation.toneClassName)} />      </PopoverTrigger>      <PopoverPopup align="start" className="w-80 max-w-full" side="bottom">        <p className="mb-2 font-medium text-sm">{presentation.label}</p>        {summary === null ? null : <p className="mb-2 text-muted-foreground text-xs">{summary}</p>}        {checks !== undefined ? (          <ChecksBody checks={checks} />        ) : environmentId !== undefined && reference !== undefined ? (          <LazyChecksBody environmentId={environmentId} reference={reference} />        ) : null}      </PopoverPopup>    </Popover>  );}