~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
104 lines · 3.5 KB Raw History
import { useQuery } from '@tanstack/react-query';
import { GitPullRequestIcon } from 'lucide-react';
import { EmptyState } from '#/components/molecules/empty-state.jsx';
import { ListBox } from '#/components/molecules/list-box.jsx';
import { ListSkeleton } from '#/components/molecules/list-skeleton.jsx';
import { PageBar } from '#/components/molecules/page-bar.jsx';
import { PageNotice } from '#/components/molecules/page-notice.jsx';
import { PullCard } from '#/components/molecules/pull-card.jsx';
import { Screen } from '#/components/molecules/screen.jsx';
import { TabBar } from '#/components/molecules/tab-bar.jsx';
import { loadPulls } from '#/lib/collab.js';
import { repoRecord } from '#/lib/git.js';

const empty = [];

/** What each tab holds, and what an empty one says. */
const TABS = [
  { key: 'open', label: 'Open', of: (pulls) => pulls.open },
  { key: 'merged', label: 'Merged', of: (pulls) => pulls.merged },
];

/**
 * Every pull request on a repository, gathered from every collaborator's own
 * copy of it.
 *
 * A pull request is a branch in one account's copy, and its state is the
 * object graph rather than a field somebody maintains: a branch canonical main
 * does not reach is open, one it reaches is merged. So this screen cannot show
 * a pull request that was merged last week or miss one somebody pushed a
 * minute ago.
 *
 * One read fills both tabs, so moving between them costs nothing.
 */
export function PullsPage({ repo, tab, space }) {
  const record = repoRecord(repo, space);
  const { data, error } = useQuery({
    queryKey: ['pulls', repo, space ?? ''],
    queryFn: () => loadPulls(repo, space),
  });

  if (!record) {
    return <PageNotice>No such repository.</PageNotice>;
  }

  const active = TABS.some((entry) => entry.key === tab) ? tab : 'open';
  const at = `/${encodeURIComponent(repo)}/pulls`;
  const shown = data ? TABS.find((entry) => entry.key === active).of(data) : [];

  return (
    <Screen
      bar={
        <PageBar tabs>
          <TabBar
            className="border-b-0"
            active={active}
            tabs={TABS.map((entry) => ({
              key: entry.key,
              label: entry.label,
              href: entry.key === 'open' ? at : `${at}/${entry.key}`,
              count: data ? entry.of(data).length : undefined,
            }))}
          />
        </PageBar>
      }
    >
      {error && <PageNotice tone="error">{error.message}</PageNotice>}
      {!data && !error && (
        <ListBox>
          <ListSkeleton />
        </ListBox>
      )}
      {data &&
        (shown.length === 0 ? (
          <ListBox>
            <EmptyState
              icon={<GitPullRequestIcon />}
              title={active === 'open' ? 'Nothing open' : 'Nothing merged'}
              description={
                active === 'open'
                  ? data.configured
                    ? 'Every branch these collaborators hold is already reachable from main.'
                    : 'No contributor has opened a pull request against this repository yet.'
                  : 'No pull request has been merged into main yet.'
              }
            />
          </ListBox>
        ) : (
          <ListBox>
            <div>
              {shown.map((pull) => (
                <PullCard
                  key={pull.id}
                  repo={repo}
                  pull={pull}
                  checks={data.checks.get(pull.id) ?? empty}
                  reviews={data.reviews.get(pull.id) ?? empty}
                />
              ))}
            </div>
          </ListBox>
        ))}
    </Screen>
  );
}