Skip to content

Commit e335413

Browse files
feat: observation deck UI — remove command panels, add code activity feed, interactive file viewer
- Dashboard: removed all 9 command panels (agents use API, not UI) - Dashboard: added Recent Pull Requests feed with expandable reviews - Dashboard: added Recent Commits feed across all repositories - Repo detail: clickable file tree loads file content via API - Repo detail: clickable commits expand to show full git diff - New API: GET /api/repos/:id/files?branch=&path= (file content) - New API: GET /api/repos/:id/files?commit=HASH (full commit diff) - git-forge: added getFileContent() and getCommitFullDiff() helpers - Removed FormInput, FormTextarea, FormSelect unused components - Added CSS for pr-feed, commit-feed, file-viewer sections - 0 ESLint errors, 0 TypeScript errors, 23-route production build
1 parent 1fff8f9 commit e335413

5 files changed

Lines changed: 555 additions & 394 deletions

File tree

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { NextResponse } from "next/server";
2+
3+
import { getCurrentObserver } from "@/lib/clerk-auth";
4+
import { db } from "@/lib/db";
5+
import { getFileContent, getCommitFullDiff } from "@/lib/git-forge";
6+
7+
export const runtime = "nodejs";
8+
9+
export async function GET(request: Request, context: { params: Promise<{ repositoryId: string }> }) {
10+
const observer = await getCurrentObserver();
11+
if (!observer) {
12+
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
13+
}
14+
15+
const { repositoryId } = await context.params;
16+
const url = new URL(request.url);
17+
const branch = url.searchParams.get("branch");
18+
const filePath = url.searchParams.get("path");
19+
const commitHash = url.searchParams.get("commit");
20+
21+
if (!db) {
22+
return NextResponse.json({ error: "Requires database" }, { status: 400 });
23+
}
24+
25+
const repository = await db.repository.findUnique({ where: { id: repositoryId }, select: { repoPath: true } });
26+
if (!repository) {
27+
return NextResponse.json({ error: "Repository not found" }, { status: 404 });
28+
}
29+
30+
try {
31+
if (commitHash) {
32+
const diff = await getCommitFullDiff(repository.repoPath, commitHash);
33+
return NextResponse.json({ type: "diff", content: diff });
34+
}
35+
36+
if (branch && filePath) {
37+
const content = await getFileContent(repository.repoPath, branch, filePath);
38+
return NextResponse.json({ type: "file", branch, path: filePath, content });
39+
}
40+
41+
return NextResponse.json({ error: "Provide ?branch=&path= or ?commit=" }, { status: 400 });
42+
} catch {
43+
return NextResponse.json({ error: "File not found or unreadable" }, { status: 404 });
44+
}
45+
}

src/app/globals.css

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1848,4 +1848,223 @@ select {
18481848
.event-item:first-child .event-dot {
18491849
animation: none;
18501850
}
1851+
}
1852+
1853+
/* ─── Code Activity Sections ─────────────────────────── */
1854+
.code-activity-section {
1855+
margin-top: 1.5rem;
1856+
}
1857+
.code-activity-section h2 {
1858+
margin-bottom: 0.25rem;
1859+
}
1860+
.section-subtitle {
1861+
color: rgba(255, 255, 255, 0.5);
1862+
font-size: 0.85rem;
1863+
margin-bottom: 1rem;
1864+
}
1865+
1866+
/* PR Feed */
1867+
.pr-feed {
1868+
display: flex;
1869+
flex-direction: column;
1870+
gap: 0.75rem;
1871+
}
1872+
.pr-feed-card {
1873+
background: rgba(255, 255, 255, 0.03);
1874+
border: 1px solid rgba(255, 255, 255, 0.06);
1875+
border-radius: 10px;
1876+
padding: 0.85rem 1rem;
1877+
cursor: pointer;
1878+
transition: border-color 0.2s, background 0.2s;
1879+
}
1880+
.pr-feed-card:hover {
1881+
border-color: rgba(255, 255, 255, 0.12);
1882+
background: rgba(255, 255, 255, 0.05);
1883+
}
1884+
.pr-feed-card.pr-expanded {
1885+
border-color: rgba(168, 130, 255, 0.3);
1886+
background: rgba(168, 130, 255, 0.04);
1887+
}
1888+
.pr-feed-header {
1889+
display: flex;
1890+
flex-direction: column;
1891+
gap: 0.35rem;
1892+
}
1893+
.pr-feed-title-row {
1894+
display: flex;
1895+
align-items: center;
1896+
gap: 0.5rem;
1897+
flex-wrap: wrap;
1898+
}
1899+
.pr-feed-meta {
1900+
display: flex;
1901+
align-items: center;
1902+
gap: 0.75rem;
1903+
font-size: 0.8rem;
1904+
color: rgba(255, 255, 255, 0.45);
1905+
}
1906+
.code-ref {
1907+
font-family: "JetBrains Mono", "Fira Code", monospace;
1908+
font-size: 0.78rem;
1909+
background: rgba(255, 255, 255, 0.05);
1910+
padding: 0.1em 0.4em;
1911+
border-radius: 4px;
1912+
color: rgba(255, 255, 255, 0.6);
1913+
}
1914+
.muted-inline {
1915+
color: rgba(255, 255, 255, 0.35);
1916+
font-size: 0.82rem;
1917+
}
1918+
1919+
/* PR expanded detail */
1920+
.pr-feed-detail {
1921+
margin-top: 0.75rem;
1922+
padding-top: 0.75rem;
1923+
border-top: 1px solid rgba(255, 255, 255, 0.06);
1924+
}
1925+
.pr-description {
1926+
font-size: 0.85rem;
1927+
color: rgba(255, 255, 255, 0.6);
1928+
line-height: 1.5;
1929+
margin-bottom: 0.75rem;
1930+
}
1931+
.pr-reviews-inline {
1932+
display: flex;
1933+
flex-direction: column;
1934+
gap: 0.4rem;
1935+
margin-bottom: 0.75rem;
1936+
}
1937+
.pr-review-chip {
1938+
display: flex;
1939+
align-items: center;
1940+
gap: 0.5rem;
1941+
font-size: 0.82rem;
1942+
padding: 0.35rem 0.6rem;
1943+
border-radius: 6px;
1944+
background: rgba(255, 255, 255, 0.04);
1945+
}
1946+
.pr-review-chip.tone-approve {
1947+
background: rgba(80, 250, 123, 0.08);
1948+
border-left: 3px solid rgba(80, 250, 123, 0.4);
1949+
}
1950+
.pr-review-chip.tone-reject {
1951+
background: rgba(255, 85, 85, 0.08);
1952+
border-left: 3px solid rgba(255, 85, 85, 0.4);
1953+
}
1954+
.review-comment {
1955+
color: rgba(255, 255, 255, 0.45);
1956+
font-style: italic;
1957+
}
1958+
.pr-view-code-link {
1959+
display: inline-block;
1960+
font-size: 0.82rem;
1961+
color: rgba(168, 130, 255, 0.8);
1962+
text-decoration: none;
1963+
transition: color 0.2s;
1964+
}
1965+
.pr-view-code-link:hover {
1966+
color: rgba(168, 130, 255, 1);
1967+
}
1968+
1969+
/* Commit Feed */
1970+
.commit-feed {
1971+
display: flex;
1972+
flex-direction: column;
1973+
gap: 0.6rem;
1974+
}
1975+
.commit-feed-card {
1976+
background: rgba(255, 255, 255, 0.03);
1977+
border: 1px solid rgba(255, 255, 255, 0.06);
1978+
border-radius: 10px;
1979+
padding: 0.75rem 1rem;
1980+
}
1981+
.commit-feed-header {
1982+
display: flex;
1983+
justify-content: space-between;
1984+
align-items: center;
1985+
gap: 0.5rem;
1986+
}
1987+
.commit-feed-meta {
1988+
display: flex;
1989+
align-items: center;
1990+
gap: 0.6rem;
1991+
font-size: 0.8rem;
1992+
color: rgba(255, 255, 255, 0.45);
1993+
margin-top: 0.35rem;
1994+
flex-wrap: wrap;
1995+
}
1996+
.language-pill {
1997+
font-size: 0.75rem;
1998+
background: rgba(168, 130, 255, 0.12);
1999+
color: rgba(168, 130, 255, 0.85);
2000+
padding: 0.15em 0.5em;
2001+
border-radius: 4px;
2002+
}
2003+
2004+
/* File viewer (repo detail) */
2005+
.file-viewer-section {
2006+
margin-top: 1.5rem;
2007+
}
2008+
.file-entry {
2009+
cursor: pointer;
2010+
padding: 0.25rem 0.4rem;
2011+
border-radius: 4px;
2012+
transition: background 0.15s;
2013+
}
2014+
.file-entry:hover {
2015+
background: rgba(255, 255, 255, 0.06);
2016+
}
2017+
.file-entry.file-active {
2018+
background: rgba(168, 130, 255, 0.1);
2019+
color: rgba(168, 130, 255, 0.9);
2020+
}
2021+
.file-content-viewer {
2022+
background: rgba(0, 0, 0, 0.3);
2023+
border: 1px solid rgba(255, 255, 255, 0.08);
2024+
border-radius: 8px;
2025+
padding: 1rem;
2026+
margin-top: 0.75rem;
2027+
font-family: "JetBrains Mono", "Fira Code", monospace;
2028+
font-size: 0.82rem;
2029+
line-height: 1.6;
2030+
white-space: pre-wrap;
2031+
overflow-x: auto;
2032+
max-height: 500px;
2033+
overflow-y: auto;
2034+
color: rgba(255, 255, 255, 0.8);
2035+
}
2036+
.file-viewer-header {
2037+
display: flex;
2038+
justify-content: space-between;
2039+
align-items: center;
2040+
margin-bottom: 0.5rem;
2041+
}
2042+
.file-viewer-header strong {
2043+
font-family: "JetBrains Mono", "Fira Code", monospace;
2044+
font-size: 0.85rem;
2045+
color: rgba(168, 130, 255, 0.85);
2046+
}
2047+
.file-viewer-close {
2048+
font-size: 0.8rem;
2049+
background: none;
2050+
border: 1px solid rgba(255, 255, 255, 0.1);
2051+
color: rgba(255, 255, 255, 0.5);
2052+
border-radius: 4px;
2053+
padding: 0.2em 0.6em;
2054+
cursor: pointer;
2055+
transition: background 0.15s;
2056+
}
2057+
.file-viewer-close:hover {
2058+
background: rgba(255, 255, 255, 0.06);
2059+
}
2060+
2061+
@media (max-width: 700px) {
2062+
.pr-feed-title-row {
2063+
flex-direction: column;
2064+
align-items: flex-start;
2065+
}
2066+
.commit-feed-header {
2067+
flex-direction: column;
2068+
align-items: flex-start;
2069+
}
18512070
}

0 commit comments

Comments
 (0)