feat(ui): add document revision diff viewer

Add a "View diff" option to the document three-dot menu (visible when
revision > 1) that opens a modal showing side-by-side changes between
revisions using react-diff-viewer-continued. Defaults to comparing the
current revision with its predecessor, with dropdowns to select any two
revisions.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
dotta 2026-04-06 08:11:50 -05:00
parent 54ac2c6fe9
commit 13ada98e78
3 changed files with 195 additions and 3 deletions

View file

@ -29,7 +29,8 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Check, ChevronDown, ChevronRight, Copy, Download, FilePenLine, FileText, MoreHorizontal, Plus, Trash2, X } from "lucide-react";
import { Check, ChevronDown, ChevronRight, Copy, Diff, Download, FilePenLine, FileText, MoreHorizontal, Plus, Trash2, X } from "lucide-react";
import { DocumentDiffModal } from "./DocumentDiffModal";
type DraftState = {
key: string;
@ -162,6 +163,7 @@ export function IssueDocumentsSection({
const [highlightDocumentKey, setHighlightDocumentKey] = useState<string | null>(null);
const [revisionMenuOpenKey, setRevisionMenuOpenKey] = useState<string | null>(null);
const [selectedRevisionIds, setSelectedRevisionIds] = useState<Record<string, string | null>>({});
const [diffViewKey, setDiffViewKey] = useState<string | null>(null);
const autosaveDebounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const copiedDocumentTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const hasScrolledToHashRef = useRef(false);
@ -929,6 +931,12 @@ export function IssueDocumentsSection({
<Download className="h-3.5 w-3.5" />
Download document
</DropdownMenuItem>
{doc.latestRevisionNumber > 1 ? (
<DropdownMenuItem onClick={() => setDiffViewKey(doc.key)}>
<Diff className="h-3.5 w-3.5" />
View diff
</DropdownMenuItem>
) : null}
{canDeleteDocuments ? <DropdownMenuSeparator /> : null}
{canDeleteDocuments ? (
<DropdownMenuItem
@ -1174,6 +1182,20 @@ export function IssueDocumentsSection({
);
})}
</div>
{diffViewKey && (() => {
const diffDoc = sortedDocuments.find((d) => d.key === diffViewKey);
if (!diffDoc) return null;
return (
<DocumentDiffModal
issueId={issue.id}
documentKey={diffDoc.key}
latestRevisionNumber={diffDoc.latestRevisionNumber}
open
onOpenChange={(open) => { if (!open) setDiffViewKey(null); }}
/>
);
})()}
</div>
);
}