RepoSettings.tsx
Raw
1import type { LabelRow, RepositoryRow } from "../../db/index.ts";
2import type { SessionUser } from "../../middleware/session.ts";
3import { Layout } from "../layout.tsx";
4import { RepoHeader } from "./RepoHeader.tsx";
5import { RepoNav } from "./RepoNav.tsx";
6
7interface RepoSettingsProps {
8 user: SessionUser;
9 repo: RepositoryRow;
10 branches: string[];
11 labels: LabelRow[];
12 success?: string;
13 error?: string;
14}
15
16export function RepoSettings({
17 user,
18 repo,
19 branches,
20 labels,
21 success,
22 error,
23}: RepoSettingsProps) {
24 return (
25 <Layout user={user} title={`Settings — ${repo.name}`}>
26 <div class="container">
27 <RepoHeader repo={repo} />
28 <RepoNav repo={repo} active="settings" user={user} />
29 {success && <p class="form-success">{success}</p>}
30 {error && <p class="form-error">{error}</p>}
31 <form
32 method="POST"
33 action={`/${repo.name}/settings`}
34 class="form-card"
35 >
36 <div class="form-group">
37 <label for="description">Description</label>
38 <input
39 id="description"
40 name="description"
41 type="text"
42 value={repo.description ?? ""}
43 placeholder="A short description"
44 />
45 </div>
46 <div class="form-group">
47 <label for="default_branch">Default branch</label>
48 {branches.length > 0 ? (
49 <select
50 id="default_branch"
51 name="default_branch"
52 class="branch-select"
53 >
54 {branches.map((b) => (
55 <option
56 value={b}
57 selected={
58 b === repo.default_branch
59 ? true
60 : undefined
61 }
62 >
63 {b}
64 </option>
65 ))}
66 </select>
67 ) : (
68 <p class="form-hint">
69 No branches yet — push your first commit to set
70 the default branch.
71 </p>
72 )}
73 </div>
74 <div class="form-group">
75 <label class="checkbox-label">
76 <input
77 type="checkbox"
78 name="is_private"
79 value="1"
80 checked={repo.is_private === 1}
81 />
82 Private repository (only visible to you)
83 </label>
84 </div>
85 <div class="form-group">
86 <label class="checkbox-label">
87 <input
88 type="checkbox"
89 name="is_pinned"
90 value="1"
91 checked={repo.is_pinned === 1}
92 />
93 Pin this repository (always shown at the top of the
94 list)
95 </label>
96 </div>
97 <div class="form-group">
98 <label class="checkbox-label">
99 <input
100 type="checkbox"
101 name="allow_user_labels"
102 value="1"
103 checked={repo.allow_user_labels === 1}
104 />
105 Allow users to add/remove labels on their own issues
106 and patches
107 </label>
108 </div>
109 <div class="form-group">
110 <label for="issue_template">
111 Issue template{" "}
112 <span class="text-muted">
113 (Markdown, prefilled when opening a new issue)
114 </span>
115 </label>
116 <textarea
117 id="issue_template"
118 name="issue_template"
119 rows="8"
120 placeholder="## Description&#10;&#10;## Steps to reproduce&#10;&#10;## Expected behavior"
121 >
122 {repo.issue_template ?? ""}
123 </textarea>
124 </div>
125 <div class="form-group">
126 <label for="patch_template">
127 Patch template{" "}
128 <span class="text-muted">
129 (Markdown, prefilled when submitting a new
130 patch)
131 </span>
132 </label>
133 <textarea
134 id="patch_template"
135 name="patch_template"
136 rows="8"
137 placeholder="## Summary&#10;&#10;## Testing"
138 >
139 {repo.patch_template ?? ""}
140 </textarea>
141 </div>
142 <button type="submit" class="btn btn-primary">
143 Save settings
144 </button>
145 </form>
146 <div class="form-card">
147 <h2 class="section-title">Labels</h2>
148 {labels.length > 0 && (
149 <div class="label-settings-list">
150 {labels.map((label) => (
151 <div class="label-settings-item">
152 <span
153 class="label-settings-swatch"
154 style={`background:${label.color}`}
155 />
156 <span class="label-settings-name">
157 {label.name}
158 </span>
159 <form
160 method="POST"
161 action={`/${repo.name}/settings/labels/delete`}
162 >
163 <input
164 type="hidden"
165 name="id"
166 value={String(label.id)}
167 />
168 <button
169 class="btn btn-danger btn-sm"
170 type="submit"
171 >
172 Delete
173 </button>
174 </form>
175 </div>
176 ))}
177 </div>
178 )}
179 <form
180 method="POST"
181 action={`/${repo.name}/settings/labels`}
182 class="label-add-form"
183 >
184 <input
185 class="form-input label-name-input"
186 type="text"
187 name="name"
188 placeholder="Label name"
189 maxlength="50"
190 required
191 />
192 <label
193 class="label-color-swatch-label"
194 title="Pick a color"
195 >
196 <input
197 type="color"
198 name="color"
199 value="#808080"
200 class="label-color-input"
201 />
202 </label>
203 <button type="submit" class="btn btn-secondary btn-sm">
204 Add label
205 </button>
206 </form>
207 </div>
208 <div class="danger-zone">
209 <h2 class="section-title danger-title">Danger zone</h2>
210 <div class="form-card danger-card">
211 <div class="danger-item">
212 <div>
213 <strong>Delete this repository</strong>
214 <p class="text-muted">
215 Once deleted, there is no going back.
216 </p>
217 </div>
218 <details class="confirm-details">
219 <summary class="btn btn-danger">
220 Delete repository
221 </summary>
222 <div class="confirm-popup">
223 Delete {repo.name}? This cannot be undone.
224 <form
225 method="POST"
226 action={`/${repo.name}/settings/delete`}
227 class="inline-form"
228 >
229 <button
230 type="submit"
231 class="btn btn-danger"
232 >
233 Yes, delete
234 </button>
235 </form>
236 </div>
237 </details>
238 </div>
239 </div>
240 </div>
241 </div>
242 </Layout>
243 );
244}
245