Skip to content
File

Blob: src/client/pages/TreePage.tsx

typescript103 lines
1import type { FileIconName } from "@/shared/web";
2import { Breadcrumbs } from "@/client/components/Breadcrumbs";
3import { EmptyState } from "@/client/components/EmptyState";
4import { FileIcon } from "@/client/components/FileIcon";
5import { type Progress, ProgressBanner } from "@/client/components/ProgressBanner";
6import { RepoNav } from "@/client/components/RepoNav";
7 
8type TreeEntry = {
9 name: string;
10 href: string;
11 isDir: boolean;
12 isSymlink: boolean;
13 iconName: FileIconName;
14 shortOid: string;
15};
16 
17type Breadcrumb = {
18 name: string;
19 href: string | null;
20};
21 
22export type TreePageProps = {
23 owner: string;
24 repo: string;
25 refEnc: string;
26 entries: TreeEntry[];
27 breadcrumbs?: Breadcrumb[];
28 parentHref?: string | null;
29 progress?: Progress;
30};
31 
32function getTreeEntryIconClass(entry: TreeEntry): string {
33 if (entry.isDir) {
34 return "text-amber-600 dark:text-amber-400";
35 }
36 if (entry.isSymlink) {
37 return "text-accent-500 dark:text-accent-400";
38 }
39 return "text-zinc-500 dark:text-zinc-400";
40}
41 
42export function TreePage({
43 owner,
44 repo,
45 refEnc,
46 entries,
47 breadcrumbs,
48 parentHref,
49 progress,
50}: TreePageProps) {
51 return (
52 <>
53 <RepoNav owner={owner} repo={repo} refEnc={refEnc} currentTab="browse" />
54 <ProgressBanner progress={progress} />
55 <div>
56 <span className="mb-1 inline-block text-xs font-semibold uppercase tracking-wider text-accent-500 dark:text-accent-400">
57 Browse
58 </span>
59 <h2 className="font-display tracking-tight">Tree</h2>
60 <Breadcrumbs items={breadcrumbs} parentHref={parentHref} />
61 <table className="mt-4 overflow-hidden rounded-2xl border border-zinc-200 shadow-xs dark:border-zinc-800/60">
62 <thead>
63 <tr>
64 <th>Name</th>
65 <th>OID</th>
66 </tr>
67 </thead>
68 <tbody>
69 {entries.length ? (
70 entries.map((entry) => (
71 <tr key={`${entry.href}-${entry.name}`}>
72 <td>
73 <FileIcon
74 name={entry.iconName}
75 className={`mr-1.5 inline-block h-4 w-4 align-[-2px] ${getTreeEntryIconClass(entry)}`}
76 />{" "}
77 <a href={entry.href}>{entry.name}</a>
78 </td>
79 <td className="text-zinc-500 dark:text-zinc-400">{entry.shortOid}</td>
80 </tr>
81 ))
82 ) : (
83 <tr>
84 <td colSpan={2}>
85 <EmptyState
86 icon={
87 <FileIcon
88 name="folder"
89 className="h-5 w-5 text-zinc-500 dark:text-zinc-400"
90 />
91 }
92 title="This tree is empty"
93 />
94 </td>
95 </tr>
96 )}
97 </tbody>
98 </table>
99 </div>
100 </>
101 );
102}