BranchList.tsx
Raw
1import type { RepositoryRow } from "../../db/index.ts";
2import { formatDateTime } from "../../lib/formatDate.ts";
3import type { SessionUser } from "../../middleware/session.ts";
4import type { BranchInfo } from "../../services/git.ts";
5import { Layout } from "../layout.tsx";
6import { Pagination } from "../Pagination.tsx";
7import { RepoHeader } from "./RepoHeader.tsx";
8import { RepoNav } from "./RepoNav.tsx";
9
10interface BranchListProps {
11 user: SessionUser | null;
12 repo: RepositoryRow;
13 branches: BranchInfo[];
14 page: number;
15 totalPages: number;
16 success?: string;
17 error?: string;
18}
19
20export function BranchList({
21 user,
22 repo,
23 branches,
24 page,
25 totalPages,
26 success,
27 error,
28}: BranchListProps) {
29 return (
30 <Layout user={user} title={`Branches — ${repo.name}`}>
31 <div class="container">
32 <RepoHeader repo={repo} />
33 <RepoNav repo={repo} active="branches" user={user} />
34 {success && <p class="form-success">{success}</p>}
35 {error && <p class="form-error">{error}</p>}
36 <div class="list-header">
37 <h2 class="list-heading">Branches</h2>
38 {user?.isAdmin && (
39 <details class="confirm-details">
40 <summary class="btn btn-primary btn-sm">
41 New branch
42 </summary>
43 <div class="confirm-popup confirm-popup-form">
44 <form
45 method="POST"
46 action={`/${repo.name}/branches/create`}
47 class="popup-form"
48 >
49 <div class="form-group">
50 <label for="new-branch-name">
51 Branch name
52 </label>
53 <input
54 id="new-branch-name"
55 name="name"
56 type="text"
57 required
58 placeholder="feature/my-branch"
59 maxlength="255"
60 />
61 </div>
62 <div class="form-group">
63 <label for="new-branch-source">
64 From
65 </label>
66 <input
67 id="new-branch-source"
68 name="source_ref"
69 type="text"
70 required
71 value={repo.default_branch}
72 placeholder="branch, tag, or commit"
73 maxlength="255"
74 />
75 </div>
76 <button
77 type="submit"
78 class="btn btn-primary btn-sm"
79 >
80 Create branch
81 </button>
82 </form>
83 </div>
84 </details>
85 )}
86 </div>
87 {branches.length === 0 ? (
88 <div class="empty-state">
89 <p>No branches yet.</p>
90 </div>
91 ) : (
92 <ul class="ref-list">
93 {branches.map((b) => (
94 <li class="ref-item">
95 <div class="ref-name-row">
96 <a
97 href={`/${repo.name}/tree/${b.name}`}
98 class="ref-name"
99 >
100 {b.name}
101 </a>
102 {b.name === repo.default_branch && (
103 <span class="badge">default</span>
104 )}
105 </div>
106 <div class="ref-meta-row">
107 {b.authorName && (
108 <span class="ref-author">
109 {b.authorName}
110 </span>
111 )}
112 {b.shortHash && (
113 <a
114 href={`/${repo.name}/commit/${b.shortHash}`}
115 class="ref-hash mono"
116 >
117 {b.shortHash}
118 </a>
119 )}
120 {b.subject && (
121 <span class="ref-subject">
122 {b.subject}
123 </span>
124 )}
125 {b.date && (
126 <time
127 class="ref-date"
128 datetime={b.date}
129 >
130 {formatDateTime(b.date)}
131 </time>
132 )}
133 {user?.isAdmin && (
134 <span class="ref-actions">
135 <details class="confirm-details confirm-details-inline">
136 <summary class="btn btn-sm">
137 Rename
138 </summary>
139 <div class="confirm-popup">
140 <form
141 method="POST"
142 action={`/${repo.name}/branches/rename`}
143 class="popup-form"
144 >
145 <input
146 type="hidden"
147 name="old_name"
148 value={b.name}
149 />
150 <input
151 name="new_name"
152 type="text"
153 required
154 placeholder="new-name"
155 value={b.name}
156 maxlength="255"
157 />
158 <button
159 type="submit"
160 class="btn btn-sm btn-primary"
161 >
162 Rename
163 </button>
164 </form>
165 </div>
166 </details>
167 {b.name !== repo.default_branch && (
168 <details class="confirm-details confirm-details-inline">
169 <summary class="btn btn-sm btn-danger">
170 Delete
171 </summary>
172 <div class="confirm-popup">
173 Delete branch{" "}
174 <strong>
175 {b.name}
176 </strong>
177 ?
178 <form
179 method="POST"
180 action={`/${repo.name}/branches/delete`}
181 class="inline-form"
182 >
183 <input
184 type="hidden"
185 name="name"
186 value={b.name}
187 />
188 <button
189 type="submit"
190 class="btn btn-sm btn-danger"
191 >
192 Yes, delete
193 </button>
194 </form>
195 </div>
196 </details>
197 )}
198 </span>
199 )}
200 </div>
201 </li>
202 ))}
203 </ul>
204 )}
205 <Pagination
206 page={page}
207 totalPages={totalPages}
208 pageUrlTemplate={`/${repo.name}/branches?page={page}`}
209 />
210 </div>
211 </Layout>
212 );
213}
214