import { useMemo, useState } from "react"; import { useQuery } from "@tanstack/react-query"; import type { DocumentRevision } from "@paperclipai/shared"; import { issuesApi } from "../api/issues"; import { queryKeys } from "../lib/queryKeys"; import { buildLineDiff, type DiffRow } from "../lib/line-diff"; import { relativeTime } from "../lib/utils"; import { Dialog, DialogContent, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; function getRevisionLabel(revision: DocumentRevision) { const actor = revision.createdByUserId ? "board" : revision.createdByAgentId ? "agent" : "system"; return `rev ${revision.revisionNumber} — ${relativeTime(revision.createdAt)} • ${actor}`; } export function DocumentDiffModal({ issueId, documentKey, latestRevisionNumber, open, onOpenChange, }: { issueId: string; documentKey: string; latestRevisionNumber: number; open: boolean; onOpenChange: (open: boolean) => void; }) { const { data: revisions } = useQuery({ queryKey: queryKeys.issues.documentRevisions(issueId, documentKey), queryFn: () => issuesApi.listDocumentRevisions(issueId, documentKey), enabled: open, }); const sortedRevisions = useMemo(() => { if (!revisions) return []; return [...revisions].sort((a, b) => b.revisionNumber - a.revisionNumber); }, [revisions]); // Default: compare previous (latestRevisionNumber - 1) with current (latestRevisionNumber) const [leftRevisionId, setLeftRevisionId] = useState(null); const [rightRevisionId, setRightRevisionId] = useState(null); const effectiveLeftId = leftRevisionId ?? sortedRevisions.find( (r) => r.revisionNumber === latestRevisionNumber - 1, )?.id ?? null; const effectiveRightId = rightRevisionId ?? sortedRevisions.find( (r) => r.revisionNumber === latestRevisionNumber, )?.id ?? null; const leftRevision = sortedRevisions.find((r) => r.id === effectiveLeftId) ?? null; const rightRevision = sortedRevisions.find((r) => r.id === effectiveRightId) ?? null; const leftBody = leftRevision?.body ?? ""; const rightBody = rightRevision?.body ?? ""; const diffRows = useMemo(() => buildLineDiff(leftBody, rightBody), [leftBody, rightBody]); const lineClassesByKind: Record = { context: "bg-transparent", removed: "bg-red-500/10 text-red-100", added: "bg-green-500/10 text-green-100", }; const markerByKind: Record = { context: " ", removed: "-", added: "+", }; return (
Diff — {documentKey}
Old
New
{!revisions ? (
Loading revisions...
) : !leftRevision || !rightRevision ? (
Select two revisions to compare.
) : leftRevision.id === rightRevision.id ? (
Both sides are the same revision.
) : (
Old New Content
{diffRows.map((row, index) => (
{row.oldLineNumber ?? ""} {row.newLineNumber ?? ""} {markerByKind[row.kind]}
                    {row.text.length > 0 ? row.text : " "}
                  
))}
)}
); }