Skip to content

Commit e3f4c1c

Browse files
Change: Connected archive FE to BE with correct filters
1 parent d3925dc commit e3f4c1c

File tree

10 files changed

+204
-115
lines changed

10 files changed

+204
-115
lines changed

api/nginx.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ server {
6161
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
6262
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type' always;
6363

64-
proxy_pass http://anonymization-service:8094;
64+
proxy_pass http://anonymization-service:8094/api/v1/anonymization/;
6565
client_max_body_size 5m;
6666
proxy_http_version 1.1;
6767
proxy_set_header Host $host;

client/src/components/DocumentArchive.tsx

Lines changed: 78 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
// ABOUTME: Document archive component that displays user's documents from backend API
22
// ABOUTME: Includes filtering, loading states, and proper error handling for document management
3-
import React, { useState, useEffect } from 'react';
3+
import { useState, useEffect } from 'react';
44
import { Link } from 'react-router-dom';
55
import { Button } from '@/components/ui/button';
66
import DocumentStatusFilter from '@/components/DocumentStatusFilter';
77
import { fetchDocuments } from '@/services/documentService';
8+
import { fetchAnonymizations } from '@/services/anonymizeService';
89
import { Document } from '@/types/document';
10+
import { ArchiveDocument } from '@/types/archiveDocument';
11+
912
import { useToast } from '@/hooks/use-toast';
1013

11-
type DocumentStatus = 'All' | 'Anonymized' | 'Original' | 'Summarized';
14+
type DocumentStatus = 'All' | 'Anonymized' | 'Original';
1215

1316
const DocumentArchive = () => {
1417
const [selectedStatus, setSelectedStatus] = useState<DocumentStatus>('All');
15-
const [documents, setDocuments] = useState<Document[]>([]);
18+
const [documents, setDocuments] = useState<ArchiveDocument[]>([]);
1619
const [loading, setLoading] = useState(true);
1720
const [error, setError] = useState<string | null>(null);
1821
const { toast } = useToast();
@@ -22,8 +25,56 @@ const DocumentArchive = () => {
2225
try {
2326
setLoading(true);
2427
setError(null);
25-
const fetchedDocuments = await fetchDocuments();
26-
setDocuments(fetchedDocuments);
28+
29+
// Fetch both original documents and anonymizations in parallel
30+
const [originalDocs, anonymizations] = await Promise.all([
31+
fetchDocuments(),
32+
fetchAnonymizations().catch((err) => {
33+
console.warn('Failed to fetch anonymizations:', err);
34+
// Show a warning toast but don't fail the entire operation
35+
toast({
36+
title: 'Warning',
37+
description:
38+
'Could not load anonymized documents. Showing original documents only.',
39+
variant: 'default',
40+
});
41+
return [];
42+
}),
43+
]);
44+
45+
// Convert original documents to archive format
46+
const archiveOriginals: ArchiveDocument[] = originalDocs.map((doc) => ({
47+
id: doc.id,
48+
fileName: doc.fileName,
49+
uploadDate: doc.uploadDate,
50+
status: 'Original' as const,
51+
documentType: 'original' as const,
52+
documentText: doc.documentText,
53+
}));
54+
55+
// Convert anonymizations to archive format
56+
const archiveAnonymized: ArchiveDocument[] = anonymizations.map(
57+
(anon) => ({
58+
id: anon.id,
59+
fileName: `${getOriginalFileName(
60+
originalDocs,
61+
anon.documentId
62+
)} (Anonymized)`,
63+
uploadDate: anon.created,
64+
status: 'Anonymized' as const,
65+
documentType: 'anonymized' as const,
66+
originalDocumentId: anon.documentId,
67+
documentText: anon.anonymizedText,
68+
})
69+
);
70+
71+
// Combine and sort by upload date (newest first)
72+
const allDocuments = [...archiveOriginals, ...archiveAnonymized].sort(
73+
(a, b) =>
74+
new Date(b.uploadDate).getTime() - new Date(a.uploadDate).getTime()
75+
);
76+
77+
setDocuments(allDocuments);
2778
} catch (err) {
2879
const errorMessage =
2980
err instanceof Error ? err.message : 'Failed to load documents';
@@ -41,6 +92,15 @@ const DocumentArchive = () => {
4192
loadDocuments();
4293
}, [toast]);
4394

95+
// Helper function to get original document filename for anonymized documents
96+
const getOriginalFileName = (
97+
originalDocs: Document[],
98+
documentId: string
99+
): string => {
100+
const originalDoc = originalDocs.find((doc) => doc.id === documentId);
101+
return originalDoc?.fileName || 'Unknown Document';
102+
};
103+
44104
const formatDate = (dateString: string) => {
45105
try {
46106
return new Date(dateString).toLocaleDateString();
@@ -49,6 +109,8 @@ const DocumentArchive = () => {
49109
}
50110
};
51111

112+
// Filter documents based on selected status
113+
52114
const filteredDocuments =
53115
selectedStatus === 'All'
54116
? documents
@@ -112,17 +174,23 @@ const DocumentArchive = () => {
112174
className={`px-2 py-0.5 rounded-full transition-all duration-200 ${
113175
doc.status === 'Anonymized'
114176
? 'bg-green-100 text-green-800 group-hover:bg-green-200'
115-
: doc.status === 'Summarized'
116-
? 'bg-blue-100 text-blue-800 group-hover:bg-blue-200'
117177
: 'bg-gray-100 text-gray-800 group-hover:bg-gray-200'
118178
}`}
119179
>
120180
{doc.status}
121181
</span>
122182
</div>
123-
<Link to={`/editor?id=${doc.id}`}>
183+
<Link
184+
to={`/editor?id=${
185+
doc.documentType === 'anonymized'
186+
? doc.originalDocumentId
187+
: doc.id
188+
}`}
189+
>
124190
<Button className="w-full transition-all duration-200 group-hover:bg-primary/90">
125-
Open Document
191+
{doc.documentType === 'anonymized'
192+
? 'View Anonymized'
193+
: 'Open Document'}
126194
</Button>
127195
</Link>
128196
</div>
@@ -136,7 +204,7 @@ const DocumentArchive = () => {
136204
? "You haven't uploaded any documents yet."
137205
: `No ${selectedStatus.toLowerCase()} documents found.`}
138206
</p>
139-
<Link to="/">
207+
<Link to="/home">
140208
<Button>Upload a document</Button>
141209
</Link>
142210
</div>

client/src/components/DocumentEditor.tsx

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
1-
import React, { useState, useEffect } from 'react';
1+
import { useState, useEffect } from 'react';
22
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
33
import { useAnonymization } from '@/hooks/useAnonymization';
44
import { useSummarization } from '@/hooks/useSummarization';
55
import AnonymizationPanel from './AnonymizationPanel';
66
import SummarizationPanel from './SummarizationPanel';
77
import EditAnonymizedDialog from './EditAnonymizedDialog';
88
import { DocumentContent } from '@/types/documentContent';
9-
import { toast } from "sonner";
10-
9+
import { toast } from 'sonner';
1110

1211
type DocumentEditorProps = {
1312
documentId?: string | null;
1413
};
1514

1615
const DocumentEditor = ({ documentId }: DocumentEditorProps) => {
17-
1816
const [activeTab, setActiveTab] = useState('anonymize');
1917
const [documentData, setDocumentData] = useState<DocumentContent>();
2018
const [selectedText, setSelectedText] = useState<string>('');
@@ -28,7 +26,6 @@ const DocumentEditor = ({ documentId }: DocumentEditorProps) => {
2826
const [isAnonymized, setIsAnonymized] = useState(false);
2927
const [isSaved, setIsSaved] = useState(false);
3028

31-
3229
// Custom hooks
3330
const {
3431
anonymizationLevel,
@@ -39,7 +36,14 @@ const DocumentEditor = ({ documentId }: DocumentEditorProps) => {
3936
handleSaveEdit,
4037
handleDownload,
4138
handleSave,
42-
} = useAnonymization(documentData, setDocumentData, isAnonymized, setIsAnonymized, isSaved, setIsSaved);
39+
} = useAnonymization(
40+
documentData,
41+
setDocumentData,
42+
isAnonymized,
43+
setIsAnonymized,
44+
isSaved,
45+
setIsSaved
46+
);
4347

4448
const {
4549
summarizationLevel,
@@ -48,30 +52,28 @@ const DocumentEditor = ({ documentId }: DocumentEditorProps) => {
4852
handleSummarizationLevel,
4953
handleGenerateSummary,
5054
getSummarizationLevelDescription,
51-
handleDownloadSummary
55+
handleDownloadSummary,
5256
} = useSummarization(documentData, setDocumentData);
5357

5458
useEffect(() => {
5559
if (documentData) {
56-
console.log("Current documentData:", documentData);
60+
console.log('Current documentData:', documentData);
5761
}
5862
}, [documentData]);
5963

60-
6164
useEffect(() => {
6265
console.log('Fetching document with ID:', documentId);
6366

6467
const documentInfo = sessionStorage.getItem('currentDocument');
6568
if (documentInfo) {
6669
const parsedInfo = JSON.parse(documentInfo);
6770
const realContent: DocumentContent = {
68-
title: (parsedInfo.fileName?.replace(/\.pdf$/i, "") || "Untitled"),
69-
paragraph: parsedInfo.documentText || "",
71+
title: parsedInfo.fileName?.replace(/\.pdf$/i, '') || 'Untitled',
72+
paragraph: parsedInfo.documentText || '',
7073
sensitive: [],
71-
summary: ""
74+
summary: '',
7275
};
7376

74-
7577
setDocumentData(realContent);
7678
}
7779
}, [documentId]);
@@ -126,7 +128,7 @@ const DocumentEditor = ({ documentId }: DocumentEditorProps) => {
126128
value={activeTab}
127129
onValueChange={(value) => {
128130
if (value === 'summarize' && !isAnonymized) {
129-
toast.warning("Please anonymize your document before summarizing.");
131+
toast.warning('Please anonymize your document before summarizing.');
130132
return;
131133
}
132134
setActiveTab(value);
@@ -136,7 +138,11 @@ const DocumentEditor = ({ documentId }: DocumentEditorProps) => {
136138
<TabsTrigger value="anonymize">Anonymize</TabsTrigger>
137139
<TabsTrigger
138140
value="summarize"
139-
className={!isAnonymized ? 'pointer-events-auto text-muted-foreground opacity-50' : ''}
141+
className={
142+
!isAnonymized
143+
? 'pointer-events-auto text-muted-foreground opacity-50'
144+
: ''
145+
}
140146
>
141147
Summarize
142148
</TabsTrigger>

client/src/components/DocumentStatusFilter.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1+
import React from 'react';
2+
import { Button } from '@/components/ui/button';
13

2-
import React from "react";
3-
import { Button } from "@/components/ui/button";
4-
5-
type DocumentStatus = "All" | "Anonymized" | "Original" | "Summarized";
4+
type DocumentStatus = 'All' | 'Anonymized' | 'Original';
65

76
interface DocumentStatusFilterProps {
87
selectedStatus: DocumentStatus;
98
onStatusChange: (status: DocumentStatus) => void;
109
}
1110

12-
const DocumentStatusFilter = ({ selectedStatus, onStatusChange }: DocumentStatusFilterProps) => {
13-
const statuses: DocumentStatus[] = ["All", "Anonymized", "Original", "Summarized"];
11+
const DocumentStatusFilter = ({
12+
selectedStatus,
13+
onStatusChange,
14+
}: DocumentStatusFilterProps) => {
15+
const statuses: DocumentStatus[] = ['All', 'Original', 'Anonymized'];
1416

1517
return (
1618
<div className="flex flex-wrap gap-2 mb-6">
@@ -20,7 +22,7 @@ const DocumentStatusFilter = ({ selectedStatus, onStatusChange }: DocumentStatus
2022
{statuses.map((status) => (
2123
<Button
2224
key={status}
23-
variant={selectedStatus === status ? "default" : "outline"}
25+
variant={selectedStatus === status ? 'default' : 'outline'}
2426
size="sm"
2527
onClick={() => onStatusChange(status)}
2628
className="transition-all duration-200"

0 commit comments

Comments
 (0)