feat(admin): Abgleich einstellbar und Schalter je Projekt

Adminbereich, Abschnitt "Automatischer Abgleich":
- ein- und ausschalten
- Abstand von 15 Minuten bis taeglich
- Projekte je Durchlauf
- fertige und archivierte auslassen
- Zustand auf einen Blick: verknuepfte Projekte, letzter und naechster
  Durchlauf, Kurzbericht des letzten Laufs
- Knopf "Jetzt abgleichen" fuer einen sofortigen Durchlauf

Der Endpunkt POST /api/admin/sync/run dient zugleich als Einstieg fuer einen
externen Zeitgeber, falls jemand lieber von aussen taktet als den eingebauten
Automatismus zu nutzen.

Im Projektdialog laesst sich ein einzelnes Projekt vom Abgleich ausnehmen -
nuetzlich bei einem Repo, dessen Token staendig Fehler wirft. Manuell
synchronisieren geht unabhaengig davon immer.

Die Zahl der in Frage kommenden Projekte wird ueber alle Konten gezaehlt: der
Abgleich ist ein Serverauftrag, keine Dateneinsicht. Ein Administrator sieht
dadurch weiterhin keine fremden Projekte.

Nachgewiesen: Durchlauf 1 aktualisiert das echte Repo und meldet das kaputte
als Fehlschlag, Durchlauf 2 stellt das kaputte zurueck, das ausgenommene
Projekt bleibt in beiden unberuehrt. Der Zeitplan loeste eigenstaendig aus.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-25 23:38:19 +02:00
co-authored by Claude Opus 5
parent ed2637877e
commit 4f2c221db6
8 changed files with 383 additions and 4 deletions
+20
View File
@@ -31,6 +31,7 @@ interface FormState {
repoUrl: string;
repoOwner: string;
repoName: string;
autoSync: boolean;
}
const EMPTY: FormState = {
@@ -47,6 +48,7 @@ const EMPTY: FormState = {
repoUrl: "",
repoOwner: "",
repoName: "",
autoSync: true,
};
export function ProjectDialog({ open, onClose, connections, project }: ProjectDialogProps) {
@@ -87,6 +89,7 @@ export function ProjectDialog({ open, onClose, connections, project }: ProjectDi
repoUrl: project.repoUrl ?? "",
repoOwner: project.repoOwner ?? "",
repoName: project.repoName ?? "",
autoSync: project.autoSync,
}
: EMPTY,
);
@@ -154,6 +157,7 @@ export function ProjectDialog({ open, onClose, connections, project }: ProjectDi
repoUrl: form.repoUrl,
repoOwner: form.repoOwner,
repoName: form.repoName,
autoSync: form.autoSync,
};
try {
@@ -414,6 +418,22 @@ export function ProjectDialog({ open, onClose, connections, project }: ProjectDi
</div>
</div>
<label className="flex cursor-pointer items-start gap-2.5 text-sm text-slate-400">
<input
type="checkbox"
checked={form.autoSync}
onChange={(event) => update("autoSync", event.target.checked)}
className="mt-0.5 h-4 w-4 accent-violet-500"
/>
<span>
Am automatischen Abgleich teilnehmen
<span className="mt-0.5 block text-[11px] text-slate-600">
Wirkt nur, wenn der Abgleich im Adminbereich eingeschaltet ist. Manuell
synchronisieren geht unabhaengig davon immer.
</span>
</span>
</label>
{repoError ? <p className="text-xs text-rose-300">{repoError}</p> : null}
{repoPickerOpen ? (