feat(ui): Repositories im Git-Panel verwalten

Eine Leiste mit allen Repositories des Projekts, sobald es mehr als eines
gibt - bei einem einzigen waere eine Leiste mit genau einem Knopf nur
Ballast. Jedes hat eigene Kennzahlen, Listen, CI und eigenen Abgleich.

Verknuepfen und Loesen laufen ueber einen eigenen Dialog mit derselben
Repo-Auswahl wie beim Projekt. Der Projektdialog bearbeitet weiterhin nur
das fuehrende: eine Liste darin wuerde den Dialog sprengen, in dem es
eigentlich um das Projekt geht.

Eine frei waehlbare Bezeichnung tritt an die Stelle von owner/name. Die
Karte zeigt "+2 Repos" und im Titel, welche es sind.

repoTitle steht in lib/git/meta statt bei den uebrigen Repository-Helfern:
lib/repositories zieht Prisma und damit node:-Module nach, die in einer
Client-Komponente nicht landen duerfen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-26 13:24:08 +02:00
co-authored by Claude Opus 5
parent a843f08211
commit b882c870c3
9 changed files with 558 additions and 67 deletions
+17 -18
View File
@@ -19,6 +19,7 @@ import {
import { ProjectDialog } from "@/components/ProjectDialog";
import { StatusSelect } from "@/components/StatusSelect";
import { Popover } from "@/components/ui/Popover";
import { repoTitle } from "@/lib/git/meta";
import { PRIORITY_META, accentOf } from "@/lib/status";
import { cn, formatDate } from "@/lib/utils";
import type { ConnectionSafe, ProjectDetail } from "@/types";
@@ -132,24 +133,22 @@ export function ProjectHeader({
angelegt {formatDate(project.createdAt)}
</span>
<span style={{ color: priority.color }}>Prioritaet: {priority.label}</span>
{project.connection ? (
<span className="inline-flex items-center gap-1.5">
{project.connection.name}
<span className="text-slate-700">·</span>
{project.connection.provider}
</span>
) : null}
{project.repoUrl ? (
<a
href={project.repoUrl}
target="_blank"
rel="noreferrer noopener"
className="inline-flex items-center gap-1.5 text-violet-300 transition-colors hover:text-violet-200"
>
Repository
<ExternalLink className="h-3 w-3" />
</a>
) : null}
{/* Alle Repositories verlinken – bei einem einzigen sieht das aus
wie vorher, bei mehreren steht jedes fuer sich. */}
{project.repositories
.filter((repository) => repository.repoUrl)
.map((repository) => (
<a
key={repository.id}
href={repository.repoUrl!}
target="_blank"
rel="noreferrer noopener"
className="inline-flex items-center gap-1.5 text-violet-300 transition-colors hover:text-violet-200"
>
{project.repositories.length === 1 ? "Repository" : repoTitle(repository)}
<ExternalLink className="h-3 w-3" />
</a>
))}
</div>
{project.tags.length > 0 ? (