Skip to content

Commit 76464e4

Browse files
feedback
1 parent aa58cd3 commit 76464e4

4 files changed

Lines changed: 59 additions & 30 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## [Unreleased]
99

1010
### Added
11-
- Added a GitHub-style git history view to the code browser: a latest-commit header above each file, a paginated commits list (file- or repo-scoped) at `/browse/<repo>@<rev>/-/commits[/<path>]`, and author and date-range filters. Also exposes `GET /api/commits/authors` in the public API. [#1150](https://github.com/sourcebot-dev/sourcebot/pull/1150)
11+
- Added commit history viewer to code browser. [#1150](https://github.com/sourcebot-dev/sourcebot/pull/1150)
12+
- Added `/api/commits/authors` to the public API to allow fetching a list of authors for a given path and revision. [#1150](https://github.com/sourcebot-dev/sourcebot/pull/1150)
1213

1314
## [4.16.15] - 2026-04-23
1415

packages/web/src/app/(app)/browse/[...path]/components/commitRow.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ export const CommitRow = ({ commit, repoName, path, pathType }: CommitRowProps)
5050
pathType: 'tree',
5151
});
5252

53-
const onCopySha = useCallback(() => {
54-
navigator.clipboard.writeText(commit.hash);
53+
const onCopySha = useCallback(async () => {
54+
await navigator.clipboard.writeText(commit.hash);
5555
toast({ description: "✅ Copied commit SHA to clipboard" });
5656
return true;
5757
}, [commit.hash, toast]);

packages/web/src/app/(app)/browse/[...path]/components/commitsPanel.tsx

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { format } from "date-fns";
22
import { GitCommitHorizontal } from "lucide-react";
3+
import Link from "next/link";
34
import { getRepoInfoByName } from "@/actions";
45
import { PathHeader } from "@/app/(app)/components/pathHeader";
6+
import { Button } from "@/components/ui/button";
57
import { Separator } from "@/components/ui/separator";
68
import { getPathType, listCommitAuthors, listCommits } from "@/features/git";
79
import { isServiceError } from "@/lib/utils";
@@ -10,6 +12,7 @@ import { dedupeCommitAuthorsByEmail, escapeGitBreLiteral } from "../../component
1012
import { CommitRow } from "./commitRow";
1113
import { CommitsPagination } from "./commitsPagination";
1214
import { DateFilter } from "./dateFilter";
15+
import { getBrowsePath } from "../../hooks/utils";
1316

1417
interface CommitsPanelProps {
1518
path: string;
@@ -75,6 +78,14 @@ export const CommitsPanel = async ({ path, repoName, revisionName, page, author,
7578
const authors = dedupeCommitAuthorsByEmail(authorsResponse.authors);
7679
const { commits, totalCount } = commitsResponse;
7780
const isLastPage = page * COMMITS_PER_PAGE >= totalCount;
81+
const hasFilters = Boolean(author || since || until);
82+
const isEmpty = commits.length === 0;
83+
const clearFiltersHref = getBrowsePath({
84+
repoName,
85+
revisionName,
86+
path,
87+
pathType: 'commits',
88+
});
7889

7990
const groups = new Map<string, { label: string; commits: typeof commits }>();
8091
for (const commit of commits) {
@@ -114,34 +125,51 @@ export const CommitsPanel = async ({ path, repoName, revisionName, page, author,
114125
</div>
115126
<Separator />
116127
<div className="flex-1 overflow-auto">
117-
{Array.from(groups.values()).map((group) => (
118-
<div key={group.label}>
119-
<div className="sticky top-0 z-10 flex flex-row items-center gap-2 px-3 py-2 bg-muted text-sm font-medium text-muted-foreground border-b">
120-
<GitCommitHorizontal className="h-4 w-4 flex-shrink-0" />
121-
{group.label}
128+
{isEmpty ? (
129+
hasFilters ? (
130+
<div className="flex flex-col items-center justify-center gap-3 py-12">
131+
<p className="text-sm text-muted-foreground">No commits match these filters</p>
132+
<Button asChild variant="outline" size="sm">
133+
<Link href={clearFiltersHref}>Clear filters</Link>
134+
</Button>
122135
</div>
123-
{group.commits.map((commit) => (
124-
<CommitRow
125-
key={commit.hash}
126-
commit={commit}
127-
repoName={repoName}
128-
path={path}
129-
pathType={headerPathType}
130-
/>
136+
) : (
137+
<div className="py-12 text-center text-sm text-muted-foreground">
138+
No commits found
139+
</div>
140+
)
141+
) : (
142+
<>
143+
{Array.from(groups.values()).map((group) => (
144+
<div key={group.label}>
145+
<div className="sticky top-0 z-10 flex flex-row items-center gap-2 px-3 py-2 bg-muted text-sm font-medium text-muted-foreground border-b">
146+
<GitCommitHorizontal className="h-4 w-4 flex-shrink-0" />
147+
{group.label}
148+
</div>
149+
{group.commits.map((commit) => (
150+
<CommitRow
151+
key={commit.hash}
152+
commit={commit}
153+
repoName={repoName}
154+
path={path}
155+
pathType={headerPathType}
156+
/>
157+
))}
158+
</div>
131159
))}
132-
</div>
133-
))}
134-
{isLastPage && (
135-
<div className="py-8 text-center text-sm text-muted-foreground">
136-
End of commit history
137-
</div>
160+
{isLastPage && (
161+
<div className="py-8 text-center text-sm text-muted-foreground">
162+
End of commit history
163+
</div>
164+
)}
165+
<CommitsPagination
166+
page={page}
167+
perPage={COMMITS_PER_PAGE}
168+
totalCount={totalCount}
169+
extraParams={{ author, since, until }}
170+
/>
171+
</>
138172
)}
139-
<CommitsPagination
140-
page={page}
141-
perPage={COMMITS_PER_PAGE}
142-
totalCount={totalCount}
143-
extraParams={{ author, since, until }}
144-
/>
145173
</div>
146174
</div>
147175
);

packages/web/src/app/(app)/browse/components/bottomPanel.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { getBrowsePath } from "../hooks/utils";
1818
import { ExploreMenu } from "@/ee/features/codeNav/components/exploreMenu";
1919
import Link from "next/link";
2020
import { useRouter } from "next/navigation";
21-
import { ExternalLink, History } from "lucide-react";
21+
import { History } from "lucide-react";
2222
import type { BrowseState } from "../browseStateProvider";
2323
import { HistoryPanel } from "./historyPanel";
2424
import { LatestCommitInfo } from "./latestCommitInfo";
@@ -134,7 +134,7 @@ export const BottomPanel = ({ order }: BottomPanelProps) => {
134134
href={fullHistoryHref}
135135
onClick={() => updateBrowseState({ isBottomPanelCollapsed: true })}
136136
>
137-
<ExternalLink className="w-4 h-4" />
137+
<History className="w-4 h-4" />
138138
View full history
139139
</Link>
140140
</Button>

0 commit comments

Comments
 (0)