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:
@@ -14,6 +14,7 @@ import {
|
||||
import { CiBadge } from "@/components/CiBadge";
|
||||
import { Sparkline } from "@/components/Sparkline";
|
||||
import { StatusSelect } from "@/components/StatusSelect";
|
||||
import { repoTitle } from "@/lib/git/meta";
|
||||
import { PRIORITY_META, accentOf } from "@/lib/status";
|
||||
import { cn, formatRelative, truncate } from "@/lib/utils";
|
||||
import { asArray, type ProjectListItem } from "@/types";
|
||||
@@ -31,7 +32,14 @@ const PROVIDER_LABEL: Record<string, string> = {
|
||||
export function ProjectCard({ project, index = 0 }: { project: ProjectListItem; index?: number }) {
|
||||
const accent = accentOf(project.accent);
|
||||
const priority = PRIORITY_META[project.priority] ?? PRIORITY_META[2];
|
||||
const snapshot = project.snapshot;
|
||||
// Auf der Karte ist nur fuer eines Platz: das fuehrende. Wie viele es
|
||||
// insgesamt sind, sagt die Zahl daneben.
|
||||
const leading = project.repositories[0] ?? null;
|
||||
const snapshot = leading?.snapshot ?? null;
|
||||
const weitere = project.repositories.length - 1;
|
||||
// Ein Fehler an irgendeinem Repo gehoert auf die Karte, nicht nur einer am
|
||||
// fuehrenden – sonst bliebe er unbemerkt.
|
||||
const syncError = project.repositories.find((repo) => repo.syncError)?.syncError ?? null;
|
||||
const activity = asArray<number>(snapshot?.commitActivity);
|
||||
const [favorite, setFavorite] = useState(project.favorite);
|
||||
|
||||
@@ -125,10 +133,20 @@ export function ProjectCard({ project, index = 0 }: { project: ProjectListItem;
|
||||
<div className="mt-4 flex flex-wrap items-center gap-x-3 gap-y-2 text-[11px] text-slate-400">
|
||||
<CiBadge state={snapshot?.ciState} name={snapshot?.ciName} compact />
|
||||
|
||||
{project.connection ? (
|
||||
{leading?.connection ? (
|
||||
<span className="glass-soft inline-flex items-center gap-1.5 px-2 py-1">
|
||||
<span className="h-1.5 w-1.5 rounded-full bg-violet-400" aria-hidden="true" />
|
||||
{PROVIDER_LABEL[project.connection.provider] ?? project.connection.provider}
|
||||
{PROVIDER_LABEL[leading.connection.provider] ?? leading.connection.provider}
|
||||
</span>
|
||||
) : null}
|
||||
|
||||
{weitere > 0 ? (
|
||||
<span
|
||||
className="inline-flex items-center gap-1.5"
|
||||
title={project.repositories.map((repo) => repoTitle(repo)).join(", ")}
|
||||
>
|
||||
<GitBranch className="h-3.5 w-3.5 text-slate-500" />+{weitere} Repo
|
||||
{weitere === 1 ? "" : "s"}
|
||||
</span>
|
||||
) : null}
|
||||
|
||||
@@ -173,11 +191,8 @@ export function ProjectCard({ project, index = 0 }: { project: ProjectListItem;
|
||||
</span>
|
||||
) : null}
|
||||
|
||||
{project.syncError ? (
|
||||
<span
|
||||
className="inline-flex items-center gap-1.5 text-rose-300/80"
|
||||
title={project.syncError}
|
||||
>
|
||||
{syncError ? (
|
||||
<span className="inline-flex items-center gap-1.5 text-rose-300/80" title={syncError}>
|
||||
<AlertTriangle className="h-3.5 w-3.5" />
|
||||
Sync-Fehler
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user