Ops-dashboard/app/git/page.tsx
Scrum4Me Agent 9e08a7c31f feat(git): /git overview page and diff viewer
Add git module with repo status overview (/git) and per-repo detail page
(/git/[repo]) featuring a color-coded diff viewer (+ green, - red).
Reads repo paths from REPO_PATHS env var, calls ops-agent git_status and
git_diff commands. Status badges: clean (green), dirty (orange),
behind-origin (blue).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 17:35:11 +02:00

54 lines
1.8 KiB
TypeScript

import { redirect } from 'next/navigation'
import { getCurrentUser } from '@/lib/session'
import { execAgent } from '@/lib/agent-client'
import { parseGitStatus, type RepoStatus } from '@/lib/parse-git'
import GitReposList from './_components/git-repos-list'
export const dynamic = 'force-dynamic'
function repoName(repoPath: string): string {
return repoPath.split('/').filter(Boolean).pop() ?? repoPath
}
export default async function GitPage() {
const user = await getCurrentUser()
if (!user) redirect('/login')
const repoPaths = (process.env.REPO_PATHS ?? '')
.split(',')
.map((p) => p.trim())
.filter(Boolean)
const initialRepos = await Promise.all(
repoPaths.map(async (path) => {
let status: RepoStatus | null = null
let error: string | null = null
try {
const output = await execAgent('git_status', [path])
status = parseGitStatus(output)
} catch (err) {
error = err instanceof Error ? err.message : 'failed'
}
return { path, name: repoName(path), status, error }
}),
)
return (
<div className="min-h-screen bg-background p-6">
<div className="mx-auto max-w-6xl space-y-6">
<div>
<h1 className="text-2xl font-semibold tracking-tight">Git Repositories</h1>
<p className="text-sm text-muted-foreground">Auto-refreshes every 30 seconds</p>
</div>
{repoPaths.length === 0 ? (
<div className="rounded-lg border border-border p-6 text-sm text-muted-foreground">
No repos configured. Set <code className="font-mono">REPO_PATHS</code> in your
environment (comma-separated absolute paths).
</div>
) : (
<GitReposList initialRepos={initialRepos} />
)}
</div>
</div>
)
}