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