NewRelease.tsx
Raw
1import config from "../../config.ts";
2import type { RepositoryRow } from "../../db/index.ts";
3import type { SessionUser } from "../../middleware/session.ts";
4import { Layout } from "../layout.tsx";
5import { RepoHeader } from "../repos/RepoHeader.tsx";
6import { RepoNav } from "../repos/RepoNav.tsx";
7
8interface NewReleaseProps {
9 user: SessionUser;
10 repo: RepositoryRow;
11 error?: string;
12 values?: {
13 create_tag?: boolean;
14 tag_name?: string;
15 revision?: string;
16 name?: string;
17 notes?: string;
18 include_source_code?: boolean;
19 };
20}
21
22export function NewRelease({ user, repo, error, values }: NewReleaseProps) {
23 const showTagFields = values?.create_tag ?? false;
24 const defaultRevision =
25 values?.revision !== undefined ? values.revision : repo.default_branch;
26 return (
27 <Layout user={user} title={`New Release — ${repo.name}`}>
28 <div class="container">
29 <RepoHeader repo={repo} />
30 <RepoNav repo={repo} active="releases" user={user} />
31 <div class="form-page">
32 <h2 class="page-title">New Release</h2>
33 {error && <div class="form-error">{error}</div>}
34 <form
35 method="post"
36 action={`/${repo.name}/releases`}
37 enctype="multipart/form-data"
38 class="form"
39 >
40 <div class="form-group">
41 <label class="form-label" for="name">
42 Release title{" "}
43 <span class="form-required">*</span>
44 </label>
45 <input
46 type="text"
47 id="name"
48 name="name"
49 class="form-input"
50 required
51 maxlength={config.MAX_TITLE_BYTES}
52 value={values?.name ?? ""}
53 placeholder="e.g. Version 1.0 — Initial Release"
54 />
55 </div>
56 <div class="form-group">
57 <label class="checkbox-label">
58 <input
59 type="checkbox"
60 id="create_tag"
61 name="create_tag"
62 value="on"
63 checked={showTagFields}
64 />
65 <span>Create a git tag for this release</span>
66 </label>
67 </div>
68 <div
69 id="tag-fields-group"
70 style={showTagFields ? "" : "display:none"}
71 >
72 <div class="form-group">
73 <label class="form-label" for="tag_name">
74 Tag name{" "}
75 <span class="form-required">*</span>
76 </label>
77 <input
78 type="text"
79 id="tag_name"
80 name="tag_name"
81 class="form-input"
82 maxlength={config.MAX_TITLE_BYTES}
83 pattern="[a-zA-Z0-9._\-+]+"
84 title="Letters, digits, dots, hyphens, underscores, and plus signs only"
85 value={values?.tag_name ?? ""}
86 placeholder="v1.0.0"
87 />
88 </div>
89 <div class="form-group">
90 <label class="form-label" for="revision">
91 Revision{" "}
92 <span class="form-required">*</span>
93 </label>
94 <input
95 type="text"
96 id="revision"
97 name="revision"
98 class="form-input monospace"
99 value={defaultRevision}
100 placeholder="branch, tag, or commit"
101 />
102 <p class="form-hint">
103 Branch, tag, or commit to tag.
104 </p>
105 </div>
106 </div>
107 <div class="form-group">
108 <label class="form-label" for="notes">
109 Release notes
110 </label>
111 <textarea
112 id="notes"
113 name="notes"
114 class="form-input form-textarea"
115 rows="8"
116 maxlength={config.MAX_TEXT_BODY_BYTES}
117 >
118 {values?.notes ?? ""}
119 </textarea>
120 </div>
121 <div class="form-group">
122 <label class="checkbox-label">
123 <input
124 type="checkbox"
125 name="include_source_code"
126 value="on"
127 checked={
128 values?.include_source_code ?? false
129 }
130 />
131 <span>
132 Include source code archives (zip, tar.gz,
133 tar.zst)
134 </span>
135 </label>
136 </div>
137 <div class="form-group">
138 <label class="form-label" for="files">
139 Attach files
140 </label>
141 <input
142 type="file"
143 id="files"
144 name="files"
145 class="form-input"
146 multiple
147 />
148 <p class="form-hint">
149 You can attach multiple files to this release.
150 </p>
151 </div>
152 <div class="form-actions">
153 <button type="submit" class="btn btn-primary">
154 Create release
155 </button>
156 <a
157 href={`/${repo.name}/releases`}
158 class="btn btn-secondary"
159 >
160 Cancel
161 </a>
162 </div>
163 </form>
164 </div>
165 </div>
166 <script>{`
167 (function() {
168 var cb = document.getElementById('create_tag');
169 var group = document.getElementById('tag-fields-group');
170 cb.addEventListener('change', function() {
171 group.style.display = cb.checked ? '' : 'none';
172 });
173 })();
174 `}</script>
175 </Layout>
176 );
177}
178