RepoHome.tsx
Raw
1import config from "../../config.ts";
2import type { RepositoryRow } from "../../db/index.ts";
3import type { SessionUser } from "../../middleware/session.ts";
4import type { TreeEntry } from "../../services/git.ts";
5import { Layout } from "../layout.tsx";
6import { BranchSelector } from "./BranchSelector.tsx";
7import { FileTreeTable } from "./FileTreeTable.tsx";
8import { RepoHeader } from "./RepoHeader.tsx";
9import { RepoNav } from "./RepoNav.tsx";
10
11interface RepoHomeProps {
12 user: SessionUser | null;
13 repo: RepositoryRow;
14 entries: TreeEntry[];
15 readmeHtml: string | null;
16 readmePath?: string;
17 hasContent: boolean;
18 branches: string[];
19 tags?: string[];
20}
21
22export function RepoHome({
23 user,
24 repo,
25 entries,
26 readmeHtml,
27 readmePath,
28 hasContent,
29 branches,
30 tags,
31}: RepoHomeProps) {
32 return (
33 <Layout user={user} title={repo.name}>
34 <div class="container">
35 <RepoHeader repo={repo} />
36 {!!repo.description && (
37 <p class="repo-description" safe>
38 {repo.description}
39 </p>
40 )}
41 <RepoNav repo={repo} active="code" user={user} />
42 {!hasContent ? (
43 <div class="empty-state">
44 <h2>This repository is empty.</h2>
45 <p>Push your first commit to get started:</p>
46 <pre class="code-setup">
47 <code safe>{`git clone ${sshUrl(repo.name)}
48cd ${repo.name}
49echo "# ${repo.name}" > README.md
50git add .
51git commit -m "Initial commit"
52git push origin main`}</code>
53 </pre>
54 </div>
55 ) : (
56 <>
57 <div class="tree-toolbar">
58 <BranchSelector
59 repoName={repo.name}
60 branches={branches}
61 tags={tags}
62 currentRef={repo.default_branch}
63 view="tree"
64 />
65 <div class="tree-toolbar-actions">
66 {branches.includes(repo.default_branch) &&
67 user?.isAdmin && (
68 <a
69 href={`/${repo.name}/new-file/${repo.default_branch}`}
70 class="btn btn-sm btn-primary"
71 >
72 New file
73 </a>
74 )}
75 <details class="clone-popup-details">
76 <summary class="btn btn-sm btn-primary">
77 Clone
78 </summary>
79 <div class="clone-popup">
80 <div class="clone-url-row">
81 <span class="clone-url-label">
82 HTTP
83 </span>
84 <input
85 type="text"
86 readonly
87 value={httpUrl(repo.name)}
88 class="clone-url-input"
89 />
90 </div>
91 {!config.SSH_DISABLED && (
92 <div class="clone-url-row">
93 <span class="clone-url-label">
94 SSH
95 </span>
96 <input
97 type="text"
98 readonly
99 value={sshUrl(repo.name)}
100 class="clone-url-input"
101 />
102 </div>
103 )}
104 </div>
105 </details>
106 </div>
107 </div>
108 <FileTreeTable
109 repoName={repo.name}
110 treeRef={repo.default_branch}
111 subpath=""
112 entries={entries}
113 />
114 {!!readmeHtml && (
115 <div class="readme-section">
116 <div class="readme-header">
117 <span>README</span>
118 {!!readmePath && (
119 <a
120 href={`/${repo.name}/raw/${repo.default_branch}/${readmePath}`}
121 class="btn btn-sm"
122 >
123 Raw
124 </a>
125 )}
126 </div>
127 <div class="markdown-body">
128 {readmeHtml as "safe"}
129 </div>
130 </div>
131 )}
132 </>
133 )}
134 </div>
135 </Layout>
136 );
137}
138
139function httpUrl(name: string) {
140 return `${config.BASE_URL}/${name}.git`;
141}
142
143function sshUrl(name: string) {
144 const host = new URL(config.BASE_URL).hostname;
145 return `ssh://git@${host}:${config.SSH_PORT}/${name}.git`;
146}
147