All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m30s
- auto-sync-cases.sh: fix broken directory scan (was looking for
status subdirs that don't exist), fix env var word-splitting bug,
add safe.directory handling and error logging
- cases.py: auto-create Gitea repo on case_create, fix
documents/original → documents/originals naming mismatch
- app.py: add GET /api/cases/{case_number}/git-status endpoint
- web-ui: add SyncIndicator component in case header showing
sync status (synced/pending/no remote) with last commit time
- pyproject.toml: add httpx dependency
- CLAUDE.md: update Paperclip wakeup API docs
- settings page: switch tag input from Select to free-text with datalist
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
63 lines
1.9 KiB
TypeScript
63 lines
1.9 KiB
TypeScript
"use client";
|
|
|
|
import { useGitStatus } from "@/lib/api/cases";
|
|
import { CheckCircle2, AlertCircle, Clock, CloudOff } from "lucide-react";
|
|
|
|
function formatRelative(iso: string): string {
|
|
const diff = Date.now() - new Date(iso).getTime();
|
|
const mins = Math.floor(diff / 60_000);
|
|
if (mins < 1) return "עכשיו";
|
|
if (mins < 60) return `לפני ${mins} דק׳`;
|
|
const hours = Math.floor(mins / 60);
|
|
if (hours < 24) return `לפני ${hours} שע׳`;
|
|
const days = Math.floor(hours / 24);
|
|
return `לפני ${days} ימים`;
|
|
}
|
|
|
|
export function SyncIndicator({ caseNumber }: { caseNumber?: string }) {
|
|
const { data, isLoading } = useGitStatus(caseNumber);
|
|
|
|
if (isLoading || !data) return null;
|
|
|
|
if (data.error === "no_repo") {
|
|
return (
|
|
<span className="inline-flex items-center gap-1 text-[0.7rem] text-ink-muted/60" title="אין ריפו מקומי">
|
|
<CloudOff className="w-3 h-3" />
|
|
</span>
|
|
);
|
|
}
|
|
|
|
const synced = data.synced;
|
|
const pending = data.dirty_files + data.commits_ahead;
|
|
|
|
let Icon = synced ? CheckCircle2 : pending > 0 ? Clock : AlertCircle;
|
|
let color = synced
|
|
? "text-success"
|
|
: pending > 0
|
|
? "text-warn"
|
|
: "text-ink-muted";
|
|
let label = synced
|
|
? "מסונכרן"
|
|
: pending > 0
|
|
? `${pending} שינויים ממתינים`
|
|
: "לא מחובר";
|
|
|
|
if (!data.has_remote) {
|
|
Icon = CloudOff;
|
|
color = "text-ink-muted/60";
|
|
label = "אין remote";
|
|
}
|
|
|
|
const time = data.last_commit_time ? formatRelative(data.last_commit_time) : null;
|
|
const tooltip = [label, time ? `commit אחרון: ${time}` : null, data.last_commit_msg]
|
|
.filter(Boolean)
|
|
.join("\n");
|
|
|
|
return (
|
|
<span className={`inline-flex items-center gap-1 text-[0.7rem] ${color}`} title={tooltip}>
|
|
<Icon className="w-3 h-3" />
|
|
<span className="hidden sm:inline">{time ?? label}</span>
|
|
</span>
|
|
);
|
|
}
|