CommitLog.tsx
Raw
1import type { RepositoryRow } from "../../db/index.ts";
2import { formatDateTime } from "../../lib/formatDate.ts";
3
4import type { SessionUser } from "../../middleware/session.ts";
5import type { CommitEntry } from "../../services/git.ts";
6import { Layout } from "../layout.tsx";
7import { RepoHeader } from "../repos/RepoHeader.tsx";
8import { BranchSelector } from "./BranchSelector.tsx";
9import { RepoNav } from "./RepoNav.tsx";
10
11interface CommitLogProps {
12 user: SessionUser | null;
13 repo: RepositoryRow;
14 ref: string;
15 commits: CommitEntry[];
16 branches: string[];
17 tags?: string[];
18 /** URL for the next (older) page, or null if this is the last page. */
19 olderUrl: string | null;
20 /** URL for the previous (newer) page, or null if this is the first page. */
21 newerUrl: string | null;
22}
23
24export function CommitLog({
25 user,
26 repo,
27 ref: logRef,
28 commits,
29 branches,
30 tags,
31 olderUrl,
32 newerUrl,
33}: CommitLogProps) {
34 return (
35 <Layout user={user} title={`Commits — ${repo.name}`}>
36 <div class="container">
37 <RepoHeader repo={repo} />
38 <RepoNav repo={repo} active="commits" user={user} />
39 <div class="commits-header">
40 <h2 class="section-title">Commits</h2>
41 <BranchSelector
42 repoName={repo.name}
43 branches={branches}
44 tags={tags}
45 currentRef={logRef}
46 view="commits"
47 />
48 </div>
49 {commits.length === 0 ? (
50 <p class="text-muted">No commits yet.</p>
51 ) : (
52 <>
53 <p class="commit-verify-hint">
54 Note: To verify signed commits locally, download the{" "}
55 <a href="/allowed_signers">allowed signers file</a>{" "}
56 and run:{" "}
57 <code class="mono">
58 git -c gpg.format=ssh -c
59 gpg.ssh.allowedSignersFile=allowed_signers
60 verify-commit &lt;hash&gt;
61 </code>
62 </p>
63 <ul class="commit-list commit-log">
64 {commits.map((c) => (
65 <li class="commit-item">
66 <a
67 href={`/${repo.name}/commit/${c.hash}`}
68 class="commit-subject"
69 safe
70 >
71 {c.subject}
72 </a>
73 <div class="commit-meta">
74 <span class="commit-author" safe>
75 {c.author}
76 </span>
77 <span class="commit-meta-right">
78 {c.sigStatus === "good" && (
79 <span class="sig-badge verified">
80 verified
81 </span>
82 )}
83 {c.sigStatus === "bad" && (
84 <span class="sig-badge unverified">
85 unverified
86 </span>
87 )}
88 <a
89 href={`/${repo.name}/commit/${c.hash}`}
90 class="commit-hash mono"
91 safe
92 >
93 {c.hash.slice(0, 7)}
94 </a>
95 <time
96 class="commit-date"
97 datetime={c.date}
98 safe
99 >
100 {formatDateTime(c.date)}
101 </time>
102 </span>
103 </div>
104 </li>
105 ))}
106 </ul>
107 </>
108 )}
109 {(!!newerUrl || !!olderUrl) && (
110 <nav
111 class="commit-cursor-nav"
112 aria-label="Commit history navigation"
113 >
114 <div class="commit-cursor-prev">
115 {!!newerUrl && (
116 <a href={newerUrl} class="pagination-btn">
117 ← Newer
118 </a>
119 )}
120 </div>
121 <div class="commit-cursor-next">
122 {!!olderUrl && (
123 <a href={olderUrl} class="pagination-btn">
124 Older →
125 </a>
126 )}
127 </div>
128 </nav>
129 )}
130 </div>
131 </Layout>
132 );
133}
134